19526
|
1 /* vi:set ts=8 sts=4 sw=4:
|
|
2 *
|
|
3 * VIM - Vi IMproved by Bram Moolenaar
|
|
4 * BeBox GUI support Copyright 1998 by Olaf Seibert.
|
|
5 * All Rights Reserved.
|
|
6 *
|
|
7 * Do ":help uganda" in Vim to read copying and usage conditions.
|
|
8 * Do ":help credits" in Vim to see a list of people who contributed.
|
|
9 *
|
|
10 * Based on "GUI support for the Buzzword Enhanced Operating System."
|
|
11 *
|
|
12 * Ported to R4 by Richard Offer <richard@whitequeen.com> Jul 99
|
|
13 *
|
|
14 * Haiku support by Siarzhuk Zharski <imker@gmx.li> Apr-Mai 2009
|
|
15 *
|
|
16 */
|
|
17
|
|
18 /*
|
|
19 * Structure of the Haiku GUI code:
|
|
20 *
|
|
21 * There are 3 threads.
|
|
22 * 1. The initial thread. In gui_mch_prepare() this gets to run the
|
|
23 * BApplication message loop. But before it starts doing that,
|
|
24 * it creates thread 2
|
|
25 * 2. The main() thread. This thread is created in gui_mch_prepare()
|
|
26 * and its purpose in life is to call main(argc, argv) again.
|
|
27 * This thread is doing the bulk of the work.
|
|
28 * 3. Sooner or later, a window is opened by the main() thread. This
|
|
29 * causes a second message loop to be created: the window thread.
|
|
30 *
|
|
31 * == alternatively ===
|
|
32 *
|
|
33 * #if RUN_BAPPLICATION_IN_NEW_THREAD...
|
|
34 *
|
|
35 * 1. The initial thread. In gui_mch_prepare() this gets to spawn
|
|
36 * thread 2. After doing that, it returns to main() to do the
|
|
37 * bulk of the work, being the main() thread.
|
|
38 * 2. Runs the BApplication.
|
|
39 * 3. The window thread, just like in the first case.
|
|
40 *
|
|
41 * This second alternative is cleaner from Vim's viewpoint. However,
|
|
42 * the BeBook seems to assume everywhere that the BApplication *must*
|
|
43 * run in the initial thread. So perhaps doing otherwise is very wrong.
|
|
44 *
|
|
45 * However, from a B_SINGLE_LAUNCH viewpoint, the first is better.
|
|
46 * If Vim is marked "Single Launch" in its application resources,
|
|
47 * and a file is dropped on the Vim icon, and another Vim is already
|
|
48 * running, the file is passed on to the earlier Vim. This happens
|
|
49 * in BApplication::Run(). So we want Vim to terminate if
|
|
50 * BApplication::Run() terminates. (See the BeBook, on BApplication.
|
|
51 * However, it seems that the second copy of Vim isn't even started
|
|
52 * in this case... which is for the better since I wouldn't know how
|
|
53 * to detect this case.)
|
|
54 *
|
|
55 * Communication between these threads occurs mostly by translating
|
|
56 * BMessages that come in and posting an appropriate translation on
|
|
57 * the VDCMP (Vim Direct Communication Message Port). Therefore the
|
|
58 * actions required for keypresses and window resizes, etc, are mostly
|
|
59 * performed in the main() thread.
|
|
60 *
|
|
61 * A notable exception to this is the Draw() event. The redrawing of
|
|
62 * the window contents is performed asynchronously from the window
|
|
63 * thread. To make this work correctly, a locking protocol is used when
|
|
64 * any thread is accessing the essential variables that are used by
|
|
65 * the window thread.
|
|
66 *
|
|
67 * This locking protocol consists of locking Vim's window. This is both
|
|
68 * convenient and necessary.
|
|
69 */
|
|
70
|
|
71 extern "C" {
|
|
72
|
|
73 #include <assert.h>
|
|
74 #include <float.h>
|
|
75 #include <syslog.h>
|
|
76
|
|
77 #include "vim.h"
|
|
78 #include "globals.h"
|
|
79 #include "proto.h"
|
|
80 #include "version.h"
|
|
81
|
|
82 } // extern "C"
|
|
83
|
|
84 // ---------------- start of header part ----------------
|
|
85
|
|
86 //#include <Alert.h>
|
|
87 #include <Application.h>
|
|
88 #include <Beep.h>
|
|
89 #include <Bitmap.h>
|
|
90 #include <Box.h>
|
|
91 #include <Button.h>
|
|
92 #include <Clipboard.h>
|
|
93 #include <Debug.h>
|
|
94 //#include <Directory.h>
|
|
95 //#include <Entry.h>
|
|
96 #include <File.h>
|
|
97 #include <FilePanel.h>
|
|
98 #include <FindDirectory.h>
|
|
99 //#include <Font.h>
|
|
100 #include <IconUtils.h>
|
|
101 #include <Input.h>
|
|
102 #include <ListView.h>
|
|
103 #include <MenuBar.h>
|
|
104 #include <MenuItem.h>
|
|
105 //#include <MessageQueue.h>
|
|
106 //#include <OS.h>
|
|
107 #include <Path.h>
|
|
108 #include <PictureButton.h>
|
|
109 #include <PopUpMenu.h>
|
|
110 //#include <Region.h>
|
|
111 #include <Resources.h>
|
|
112 //#include <Roster.h>
|
|
113 #include <Screen.h>
|
|
114 #include <ScrollBar.h>
|
|
115 #include <ScrollView.h>
|
|
116 #include <String.h>
|
|
117 #include <StringView.h>
|
|
118 //#include <SupportDefs.h>
|
|
119 #include <TabView.h>
|
|
120 #include <TextControl.h>
|
|
121 #include <TextView.h>
|
|
122 #include <TranslationUtils.h>
|
|
123 #include <TranslatorFormats.h>
|
|
124 #include <View.h>
|
|
125 #include <Window.h>
|
|
126
|
|
127 class VimApp;
|
|
128 class VimFormView;
|
|
129 class VimTextAreaView;
|
|
130 class VimWindow;
|
|
131 class VimToolbar;
|
|
132 class VimTabLine;
|
|
133
|
|
134 extern key_map *keyMap;
|
|
135 extern char *keyMapChars;
|
|
136
|
|
137 extern int main(int argc, char **argv);
|
|
138
|
|
139 #ifndef B_MAX_PORT_COUNT
|
|
140 #define B_MAX_PORT_COUNT 255
|
|
141 #endif
|
|
142
|
|
143 // VimApp seems comparable to the X "vimShell"
|
|
144 class VimApp: public BApplication
|
|
145 {
|
|
146 typedef BApplication Inherited;
|
|
147 public:
|
|
148 VimApp(const char *appsig);
|
|
149 ~VimApp();
|
|
150
|
|
151 // callbacks:
|
|
152 #if 0
|
|
153 virtual void DispatchMessage(BMessage *m, BHandler *h)
|
|
154 {
|
|
155 m->PrintToStream();
|
|
156 Inherited::DispatchMessage(m, h);
|
|
157 }
|
|
158 #endif
|
|
159 virtual void ReadyToRun();
|
|
160 virtual void ArgvReceived(int32 argc, char **argv);
|
|
161 virtual void RefsReceived(BMessage *m);
|
|
162 virtual bool QuitRequested();
|
|
163 virtual void MessageReceived(BMessage *m);
|
|
164
|
|
165 static void SendRefs(BMessage *m, bool changedir);
|
|
166
|
|
167 sem_id fFilePanelSem;
|
|
168 BFilePanel* fFilePanel;
|
|
169 BPath fBrowsedPath;
|
|
170 private:
|
|
171 };
|
|
172
|
|
173 class VimWindow: public BWindow
|
|
174 {
|
|
175 typedef BWindow Inherited;
|
|
176 public:
|
|
177 VimWindow();
|
|
178 ~VimWindow();
|
|
179
|
|
180 // virtual void DispatchMessage(BMessage *m, BHandler *h);
|
|
181 virtual void WindowActivated(bool active);
|
|
182 virtual bool QuitRequested();
|
|
183
|
|
184 VimFormView *formView;
|
|
185
|
|
186 private:
|
|
187 void init();
|
|
188
|
|
189 };
|
|
190
|
|
191 class VimFormView: public BView
|
|
192 {
|
|
193 typedef BView Inherited;
|
|
194 public:
|
|
195 VimFormView(BRect frame);
|
|
196 ~VimFormView();
|
|
197
|
|
198 // callbacks:
|
|
199 virtual void AllAttached();
|
|
200 virtual void FrameResized(float new_width, float new_height);
|
|
201
|
|
202 #define MENUBAR_MARGIN 1
|
|
203 float MenuHeight() const
|
|
204 { return menuBar ? menuBar->Frame().Height() + MENUBAR_MARGIN: 0; }
|
|
205 BMenuBar *MenuBar() const
|
|
206 { return menuBar; }
|
|
207
|
|
208 private:
|
|
209 void init(BRect);
|
|
210
|
|
211 BMenuBar *menuBar;
|
|
212 VimTextAreaView *textArea;
|
|
213
|
|
214 #ifdef FEAT_TOOLBAR
|
|
215 public:
|
|
216 float ToolbarHeight() const;
|
|
217 VimToolbar *ToolBar() const
|
|
218 { return toolBar; }
|
|
219 private:
|
|
220 VimToolbar *toolBar;
|
|
221 #endif
|
|
222
|
|
223 #ifdef FEAT_GUI_TABLINE
|
|
224 public:
|
|
225 VimTabLine *TabLine() const { return tabLine; }
|
|
226 bool IsShowingTabLine() const { return showingTabLine; }
|
|
227 void SetShowingTabLine(bool showing) { showingTabLine = showing; }
|
|
228 float TablineHeight() const;
|
|
229 private:
|
|
230 VimTabLine *tabLine;
|
|
231 int showingTabLine;
|
|
232 #endif
|
|
233 };
|
|
234
|
|
235 class VimTextAreaView: public BView
|
|
236 {
|
|
237 typedef BView Inherited;
|
|
238 public:
|
|
239 VimTextAreaView(BRect frame);
|
|
240 ~VimTextAreaView();
|
|
241
|
|
242 // callbacks:
|
|
243 virtual void Draw(BRect updateRect);
|
|
244 virtual void KeyDown(const char *bytes, int32 numBytes);
|
|
245 virtual void MouseDown(BPoint point);
|
|
246 virtual void MouseUp(BPoint point);
|
|
247 virtual void MouseMoved(BPoint point, uint32 transit, const BMessage *message);
|
|
248 virtual void MessageReceived(BMessage *m);
|
|
249
|
|
250 // own functions:
|
|
251 int mchInitFont(char_u *name);
|
|
252 void mchDrawString(int row, int col, char_u *s, int len, int flags);
|
|
253 void mchClearBlock(int row1, int col1, int row2, int col2);
|
|
254 void mchClearAll();
|
|
255 void mchDeleteLines(int row, int num_lines);
|
|
256 void mchInsertLines(int row, int num_lines);
|
|
257
|
|
258 static void guiSendMouseEvent(int button, int x, int y, int repeated_click, int_u modifiers);
|
|
259 static void guiMouseMoved(int x, int y);
|
|
260 static void guiBlankMouse(bool should_hide);
|
|
261 static int_u mouseModifiersToVim(int32 beModifiers);
|
|
262
|
|
263 int32 mouseDragEventCount;
|
|
264
|
|
265 #ifdef FEAT_MBYTE_IME
|
|
266 void DrawIMString(void);
|
|
267 #endif
|
|
268
|
|
269 private:
|
|
270 void init(BRect);
|
|
271
|
|
272 int_u vimMouseButton;
|
|
273 int_u vimMouseModifiers;
|
|
274
|
|
275 #ifdef FEAT_MBYTE_IME
|
|
276 struct {
|
|
277 BMessenger* messenger;
|
|
278 BMessage* message;
|
|
279 BPoint location;
|
|
280 int row;
|
|
281 int col;
|
|
282 int count;
|
|
283 } IMData;
|
|
284 #endif
|
|
285 };
|
|
286
|
|
287 class VimScrollBar: public BScrollBar
|
|
288 {
|
|
289 typedef BScrollBar Inherited;
|
|
290 public:
|
|
291 VimScrollBar(scrollbar_T *gsb, orientation posture);
|
|
292 ~VimScrollBar();
|
|
293
|
|
294 virtual void ValueChanged(float newValue);
|
|
295 virtual void MouseUp(BPoint where);
|
|
296 void SetValue(float newval);
|
|
297 scrollbar_T *getGsb()
|
|
298 { return gsb; }
|
|
299
|
|
300 int32 scrollEventCount;
|
|
301
|
|
302 private:
|
|
303 scrollbar_T *gsb;
|
|
304 float ignoreValue;
|
|
305 };
|
|
306
|
|
307
|
|
308 #ifdef FEAT_TOOLBAR
|
|
309
|
|
310 class VimToolbar : public BBox
|
|
311 {
|
|
312 static BBitmap *normalButtonsBitmap;
|
|
313 static BBitmap *grayedButtonsBitmap;
|
|
314
|
|
315 BBitmap *LoadVimBitmap(const char* fileName);
|
|
316 bool GetPictureFromBitmap(BPicture *pictureTo, int32 index, BBitmap *bitmapFrom, bool pressed);
|
|
317 bool ModifyBitmapToGrayed(BBitmap *bitmap);
|
|
318
|
|
319 BList fButtonsList;
|
|
320 void InvalidateLayout();
|
|
321
|
|
322 public:
|
|
323 VimToolbar(BRect frame, const char * name);
|
|
324 ~VimToolbar();
|
|
325
|
|
326 bool PrepareButtonBitmaps();
|
|
327
|
|
328 bool AddButton(int32 index, vimmenu_T *menu);
|
|
329 bool RemoveButton(vimmenu_T *menu);
|
|
330 bool GrayButton(vimmenu_T *menu, int grey);
|
|
331
|
|
332 float ToolbarHeight() const;
|
|
333 virtual void AttachedToWindow();
|
|
334 };
|
|
335
|
|
336 BBitmap *VimToolbar::normalButtonsBitmap = NULL;
|
|
337 BBitmap *VimToolbar::grayedButtonsBitmap = NULL;
|
|
338
|
|
339 const float ToolbarMargin = 3.;
|
|
340 const float ButtonMargin = 3.;
|
|
341
|
|
342 #endif //FEAT_TOOLBAR
|
|
343
|
|
344 #ifdef FEAT_GUI_TABLINE
|
|
345
|
|
346 class VimTabLine : public BTabView
|
|
347 {
|
|
348 public:
|
|
349 class VimTab : public BTab {
|
|
350 public:
|
|
351 VimTab() : BTab(new BView(BRect(), "-Empty-", 0, 0)) {}
|
|
352
|
|
353 virtual void Select(BView* owner);
|
|
354 };
|
|
355
|
|
356 VimTabLine(BRect r) : BTabView(r, "vimTabLine", B_WIDTH_FROM_LABEL,
|
|
357 B_FOLLOW_LEFT | B_FOLLOW_TOP | B_FOLLOW_RIGHT, B_WILL_DRAW | B_FRAME_EVENTS) {}
|
|
358
|
|
359 float TablineHeight() const;
|
|
360 virtual void MouseDown(BPoint point);
|
|
361 };
|
|
362
|
|
363 #endif //FEAT_GUI_TABLINE
|
|
364
|
|
365
|
|
366 // For caching the fonts that are used;
|
|
367 // Vim seems rather sloppy in this regard.
|
|
368 class VimFont: public BFont
|
|
369 {
|
|
370 typedef BFont Inherited;
|
|
371 public:
|
|
372 VimFont();
|
|
373 VimFont(const VimFont *rhs);
|
|
374 VimFont(const BFont *rhs);
|
|
375 VimFont(const VimFont &rhs);
|
|
376 ~VimFont();
|
|
377
|
|
378 VimFont *next;
|
|
379 int refcount;
|
|
380 char_u *name;
|
|
381
|
|
382 private:
|
|
383 void init();
|
|
384 };
|
|
385
|
|
386 #if defined(FEAT_GUI_DIALOG)
|
|
387
|
|
388 class VimDialog : public BWindow
|
|
389 {
|
|
390 typedef BWindow Inherited;
|
|
391
|
|
392 BButton* _CreateButton(int32 which, const char* label);
|
|
393
|
|
394 public:
|
|
395
|
|
396 class View : public BView {
|
|
397 typedef BView Inherited;
|
|
398
|
|
399 public:
|
|
400 View(BRect frame);
|
|
401 ~View();
|
|
402
|
|
403 virtual void Draw(BRect updateRect);
|
|
404 void InitIcon(int32 type);
|
|
405
|
|
406 private:
|
|
407 BBitmap* fIconBitmap;
|
|
408 };
|
|
409
|
|
410 VimDialog(int type, const char *title, const char *message,
|
|
411 const char *buttons, int dfltbutton, const char *textfield,
|
|
412 int ex_cmd);
|
|
413 ~VimDialog();
|
|
414
|
|
415 int Go();
|
|
416
|
|
417 virtual void MessageReceived(BMessage *msg);
|
|
418
|
|
419 private:
|
|
420 sem_id fDialogSem;
|
|
421 int fDialogValue;
|
|
422 BList fButtonsList;
|
|
423 BTextView* fMessageView;
|
|
424 BTextControl* fInputControl;
|
|
425 const char* fInputValue;
|
|
426 };
|
|
427
|
|
428 class VimSelectFontDialog : public BWindow
|
|
429 {
|
|
430 typedef BWindow Inherited;
|
|
431
|
|
432 void _CleanList(BListView* list);
|
|
433 void _UpdateFontStyles();
|
|
434 void _UpdateSizeInputPreview();
|
|
435 void _UpdateFontPreview();
|
|
436 bool _UpdateFromListItem(BListView* list, char* text, int textSize);
|
|
437 public:
|
|
438
|
|
439 VimSelectFontDialog(font_family* family, font_style* style, float* size);
|
|
440 ~VimSelectFontDialog();
|
|
441
|
|
442 bool Go();
|
|
443
|
|
444 virtual void MessageReceived(BMessage *msg);
|
|
445
|
|
446 private:
|
|
447 status_t fStatus;
|
|
448 sem_id fDialogSem;
|
|
449 bool fDialogValue;
|
|
450 font_family* fFamily;
|
|
451 font_style* fStyle;
|
|
452 float* fSize;
|
|
453 font_family fFontFamily;
|
|
454 font_style fFontStyle;
|
|
455 float fFontSize;
|
|
456 BStringView* fPreview;
|
|
457 BListView* fFamiliesList;
|
|
458 BListView* fStylesList;
|
|
459 BListView* fSizesList;
|
|
460 BTextControl* fSizesInput;
|
|
461 };
|
|
462
|
|
463 #endif // FEAT_GUI_DIALOG
|
|
464
|
|
465 // ---------------- end of GUI classes ----------------
|
|
466
|
|
467 struct MainArgs {
|
|
468 int argc;
|
|
469 char **argv;
|
|
470 };
|
|
471
|
|
472 // These messages are copied through the VDCMP.
|
|
473 // Therefore they ought not to have anything fancy.
|
|
474 // They must be of POD type (Plain Old Data)
|
|
475 // as the C++ standard calls them.
|
|
476
|
|
477 #define KEY_MSG_BUFSIZ 7
|
|
478 #if KEY_MSG_BUFSIZ < MAX_KEY_CODE_LEN
|
|
479 #error Increase KEY_MSG_BUFSIZ!
|
|
480 #endif
|
|
481
|
|
482 struct VimKeyMsg {
|
|
483 char_u length;
|
|
484 char_u chars[KEY_MSG_BUFSIZ]; // contains Vim encoding
|
|
485 bool csi_escape;
|
|
486 };
|
|
487
|
|
488 struct VimResizeMsg {
|
|
489 int width;
|
|
490 int height;
|
|
491 };
|
|
492
|
|
493 struct VimScrollBarMsg {
|
|
494 VimScrollBar *sb;
|
|
495 long value;
|
|
496 int stillDragging;
|
|
497 };
|
|
498
|
|
499 struct VimMenuMsg {
|
|
500 vimmenu_T *guiMenu;
|
|
501 };
|
|
502
|
|
503 struct VimMouseMsg {
|
|
504 int button;
|
|
505 int x;
|
|
506 int y;
|
|
507 int repeated_click;
|
|
508 int_u modifiers;
|
|
509 };
|
|
510
|
|
511 struct VimMouseMovedMsg {
|
|
512 int x;
|
|
513 int y;
|
|
514 };
|
|
515
|
|
516 struct VimFocusMsg {
|
|
517 bool active;
|
|
518 };
|
|
519
|
|
520 struct VimRefsMsg {
|
|
521 BMessage *message;
|
|
522 bool changedir;
|
|
523 };
|
|
524
|
|
525 struct VimTablineMsg {
|
|
526 int index;
|
|
527 };
|
|
528
|
|
529 struct VimTablineMenuMsg {
|
|
530 int index;
|
|
531 int event;
|
|
532 };
|
|
533
|
|
534 struct VimMsg {
|
|
535 enum VimMsgType {
|
|
536 Key, Resize, ScrollBar, Menu, Mouse, MouseMoved, Focus, Refs, Tabline, TablineMenu
|
|
537 };
|
|
538
|
|
539 union {
|
|
540 struct VimKeyMsg Key;
|
|
541 struct VimResizeMsg NewSize;
|
|
542 struct VimScrollBarMsg Scroll;
|
|
543 struct VimMenuMsg Menu;
|
|
544 struct VimMouseMsg Mouse;
|
|
545 struct VimMouseMovedMsg MouseMoved;
|
|
546 struct VimFocusMsg Focus;
|
|
547 struct VimRefsMsg Refs;
|
|
548 struct VimTablineMsg Tabline;
|
|
549 struct VimTablineMenuMsg TablineMenu;
|
|
550 } u;
|
|
551 };
|
|
552
|
|
553 #define RGB(r, g, b) ((char_u)(r) << 16 | (char_u)(g) << 8 | (char_u)(b) << 0)
|
|
554 #define GUI_TO_RGB(g) { (g) >> 16, (g) >> 8, (g) >> 0, 255 }
|
|
555
|
|
556 // ---------------- end of header part ----------------
|
|
557
|
|
558 static struct specialkey
|
|
559 {
|
|
560 uint16 BeKeys;
|
|
561 #define KEY(a,b) ((a)<<8|(b))
|
|
562 #define K(a) KEY(0,a) // for ASCII codes
|
|
563 #define F(b) KEY(1,b) // for scancodes
|
|
564 char_u vim_code0;
|
|
565 char_u vim_code1;
|
|
566 } special_keys[] =
|
|
567 {
|
|
568 {K(B_UP_ARROW), 'k', 'u'},
|
|
569 {K(B_DOWN_ARROW), 'k', 'd'},
|
|
570 {K(B_LEFT_ARROW), 'k', 'l'},
|
|
571 {K(B_RIGHT_ARROW), 'k', 'r'},
|
|
572 {K(B_BACKSPACE), 'k', 'b'},
|
|
573 {K(B_INSERT), 'k', 'I'},
|
|
574 {K(B_DELETE), 'k', 'D'},
|
|
575 {K(B_HOME), 'k', 'h'},
|
|
576 {K(B_END), '@', '7'},
|
|
577 {K(B_PAGE_UP), 'k', 'P'}, // XK_Prior
|
|
578 {K(B_PAGE_DOWN), 'k', 'N'}, // XK_Next,
|
|
579
|
|
580 #define FIRST_FUNCTION_KEY 11
|
|
581 {F(B_F1_KEY), 'k', '1'},
|
|
582 {F(B_F2_KEY), 'k', '2'},
|
|
583 {F(B_F3_KEY), 'k', '3'},
|
|
584 {F(B_F4_KEY), 'k', '4'},
|
|
585 {F(B_F5_KEY), 'k', '5'},
|
|
586 {F(B_F6_KEY), 'k', '6'},
|
|
587 {F(B_F7_KEY), 'k', '7'},
|
|
588 {F(B_F8_KEY), 'k', '8'},
|
|
589 {F(B_F9_KEY), 'k', '9'},
|
|
590 {F(B_F10_KEY), 'k', ';'},
|
|
591
|
|
592 {F(B_F11_KEY), 'F', '1'},
|
|
593 {F(B_F12_KEY), 'F', '2'},
|
|
594 // {XK_F13, 'F', '3'}, // would be print screen
|
|
595 // sysreq
|
|
596 {F(0x0F), 'F', '4'}, // scroll lock
|
|
597 {F(0x10), 'F', '5'}, // pause/break
|
|
598 // {XK_F16, 'F', '6'},
|
|
599 // {XK_F17, 'F', '7'},
|
|
600 // {XK_F18, 'F', '8'},
|
|
601 // {XK_F19, 'F', '9'},
|
|
602 // {XK_F20, 'F', 'A'},
|
|
603 // {XK_F21, 'F', 'B'},
|
|
604 // {XK_F22, 'F', 'C'},
|
|
605 // {XK_F23, 'F', 'D'},
|
|
606 // {XK_F24, 'F', 'E'},
|
|
607 // {XK_F25, 'F', 'F'},
|
|
608 // {XK_F26, 'F', 'G'},
|
|
609 // {XK_F27, 'F', 'H'},
|
|
610 // {XK_F28, 'F', 'I'},
|
|
611 // {XK_F29, 'F', 'J'},
|
|
612 // {XK_F30, 'F', 'K'},
|
|
613 // {XK_F31, 'F', 'L'},
|
|
614 // {XK_F32, 'F', 'M'},
|
|
615 // {XK_F33, 'F', 'N'},
|
|
616 // {XK_F34, 'F', 'O'},
|
|
617 // {XK_F35, 'F', 'P'}, // keysymdef.h defines up to F35
|
|
618
|
|
619 // {XK_Help, '%', '1'}, // XK_Help
|
|
620 {F(B_PRINT_KEY), '%', '9'},
|
|
621
|
|
622 #if 0
|
|
623 // Keypad keys:
|
|
624 {F(0x48), 'k', 'l'}, // XK_KP_Left
|
|
625 {F(0x4A), 'k', 'r'}, // XK_KP_Right
|
|
626 {F(0x38), 'k', 'u'}, // XK_KP_Up
|
|
627 {F(0x59), 'k', 'd'}, // XK_KP_Down
|
|
628 {F(0x64), 'k', 'I'}, // XK_KP_Insert
|
|
629 {F(0x65), 'k', 'D'}, // XK_KP_Delete
|
|
630 {F(0x37), 'k', 'h'}, // XK_KP_Home
|
|
631 {F(0x58), '@', '7'}, // XK_KP_End
|
|
632 {F(0x39), 'k', 'P'}, // XK_KP_Prior
|
|
633 {F(0x60), 'k', 'N'}, // XK_KP_Next
|
|
634 {F(0x49), '&', '8'}, // XK_Undo, keypad 5
|
|
635 #endif
|
|
636
|
|
637 // End of list marker:
|
|
638 {0, 0, 0}
|
|
639 };
|
|
640
|
|
641 #define NUM_SPECIAL_KEYS (sizeof(special_keys)/sizeof(special_keys[0]))
|
|
642
|
|
643 // ---------------- VimApp ----------------
|
|
644
|
|
645 static void
|
|
646 docd(BPath &path)
|
|
647 {
|
|
648 mch_chdir((char *)path.Path());
|
|
649 // Do this to get the side effects of a :cd command
|
|
650 do_cmdline_cmd((char_u *)"cd .");
|
|
651 }
|
|
652
|
|
653 static void
|
|
654 drop_callback(void *cookie)
|
|
655 {
|
|
656 // TODO here we could handle going to a specific position in the dropped
|
|
657 // file (see src/gui_mac.c)
|
|
658 // Update the screen display
|
|
659 update_screen(NOT_VALID);
|
|
660 }
|
|
661
|
|
662 // Really handle dropped files and folders.
|
|
663 static void
|
|
664 RefsReceived(BMessage *m, bool changedir)
|
|
665 {
|
|
666 uint32 type;
|
|
667 int32 count;
|
|
668
|
|
669 m->PrintToStream();
|
|
670 switch (m->what) {
|
|
671 case B_REFS_RECEIVED:
|
|
672 case B_SIMPLE_DATA:
|
|
673 m->GetInfo("refs", &type, &count);
|
|
674 if (type != B_REF_TYPE)
|
|
675 goto bad;
|
|
676 break;
|
|
677 case B_ARGV_RECEIVED:
|
|
678 m->GetInfo("argv", &type, &count);
|
|
679 if (type != B_STRING_TYPE)
|
|
680 goto bad;
|
|
681 if (changedir) {
|
|
682 char *dirname;
|
|
683 if (m->FindString("cwd", (const char **) &dirname) == B_OK) {
|
|
684 chdir(dirname);
|
|
685 do_cmdline_cmd((char_u *)"cd .");
|
|
686 }
|
|
687 }
|
|
688 break;
|
|
689 default:
|
|
690 bad:
|
|
691 /*fprintf(stderr, "bad!\n"); */
|
|
692 delete m;
|
|
693 return;
|
|
694 }
|
|
695
|
|
696 #ifdef FEAT_VISUAL
|
|
697 reset_VIsual();
|
|
698 #endif
|
|
699
|
|
700 char_u **fnames;
|
|
701 fnames = (char_u **) alloc(count * sizeof(char_u *));
|
|
702 int fname_index = 0;
|
|
703
|
|
704 switch (m->what) {
|
|
705 case B_REFS_RECEIVED:
|
|
706 case B_SIMPLE_DATA:
|
|
707 // fprintf(stderr, "case B_REFS_RECEIVED\n");
|
|
708 for (int i = 0; i < count; ++i)
|
|
709 {
|
|
710 entry_ref ref;
|
|
711 if (m->FindRef("refs", i, &ref) == B_OK) {
|
|
712 BEntry entry(&ref, false);
|
|
713 BPath path;
|
|
714 entry.GetPath(&path);
|
|
715
|
|
716 // Change to parent directory?
|
|
717 if (changedir) {
|
|
718 BPath parentpath;
|
|
719 path.GetParent(&parentpath);
|
|
720 docd(parentpath);
|
|
721 }
|
|
722
|
|
723 // Is it a directory? If so, cd into it.
|
|
724 BDirectory bdir(&ref);
|
|
725 if (bdir.InitCheck() == B_OK) {
|
|
726 // don't cd if we already did it
|
|
727 if (!changedir)
|
|
728 docd(path);
|
|
729 } else {
|
|
730 mch_dirname(IObuff, IOSIZE);
|
|
731 char_u *fname = shorten_fname((char_u *)path.Path(), IObuff);
|
|
732 if (fname == NULL)
|
|
733 fname = (char_u *)path.Path();
|
|
734 fnames[fname_index++] = vim_strsave(fname);
|
|
735 // fprintf(stderr, "%s\n", fname);
|
|
736 }
|
|
737
|
|
738 // Only do it for the first file/dir
|
|
739 changedir = false;
|
|
740 }
|
|
741 }
|
|
742 break;
|
|
743 case B_ARGV_RECEIVED:
|
|
744 // fprintf(stderr, "case B_ARGV_RECEIVED\n");
|
|
745 for (int i = 1; i < count; ++i)
|
|
746 {
|
|
747 char *fname;
|
|
748
|
|
749 if (m->FindString("argv", i, (const char **) &fname) == B_OK) {
|
|
750 fnames[fname_index++] = vim_strsave((char_u *)fname);
|
|
751 }
|
|
752 }
|
|
753 break;
|
|
754 default:
|
|
755 // fprintf(stderr, "case default\n");
|
|
756 break;
|
|
757 }
|
|
758
|
|
759 delete m;
|
|
760
|
|
761 // Handle the drop, :edit to get to the file
|
|
762 if (fname_index > 0) {
|
|
763 handle_drop(fname_index, fnames, FALSE, drop_callback, NULL);
|
|
764
|
|
765 setcursor();
|
|
766 out_flush();
|
|
767 } else {
|
|
768 vim_free(fnames);
|
|
769 }
|
|
770 }
|
|
771
|
|
772 VimApp::VimApp(const char *appsig):
|
|
773 BApplication(appsig),
|
|
774 fFilePanelSem(-1),
|
|
775 fFilePanel(NULL)
|
|
776 {
|
|
777 }
|
|
778
|
|
779 VimApp::~VimApp()
|
|
780 {
|
|
781 }
|
|
782
|
|
783 void
|
|
784 VimApp::ReadyToRun()
|
|
785 {
|
|
786 /*
|
|
787 * Apparently signals are inherited by the created thread -
|
|
788 * disable the most annoying ones.
|
|
789 */
|
|
790 signal(SIGINT, SIG_IGN);
|
|
791 signal(SIGQUIT, SIG_IGN);
|
|
792 }
|
|
793
|
|
794 void
|
|
795 VimApp::ArgvReceived(int32 arg_argc, char **arg_argv)
|
|
796 {
|
|
797 if (!IsLaunching()) {
|
|
798 /*
|
|
799 * This can happen if we are set to Single or Exclusive
|
|
800 * Launch. Be nice and open the file(s).
|
|
801 */
|
|
802 if (gui.vimWindow)
|
|
803 gui.vimWindow->Minimize(false);
|
|
804 BMessage *m = CurrentMessage();
|
|
805 DetachCurrentMessage();
|
|
806 SendRefs(m, true);
|
|
807 }
|
|
808 }
|
|
809
|
|
810 void
|
|
811 VimApp::RefsReceived(BMessage *m)
|
|
812 {
|
|
813 // Horrible hack!!! XXX XXX XXX
|
|
814 // The real problem is that b_start_ffc is set too late for
|
|
815 // the initial empty buffer. As a result the window will be
|
|
816 // split instead of abandoned.
|
|
817 int limit = 15;
|
|
818 while (--limit >= 0 && (curbuf == NULL || curbuf->b_start_ffc == 0))
|
|
819 snooze(100000); // 0.1 s
|
|
820 if (gui.vimWindow)
|
|
821 gui.vimWindow->Minimize(false);
|
|
822 DetachCurrentMessage();
|
|
823 SendRefs(m, true);
|
|
824 }
|
|
825
|
|
826 /*
|
|
827 * Pass a BMessage on to the main() thread.
|
|
828 * Caller must have detached the message.
|
|
829 */
|
|
830 void
|
|
831 VimApp::SendRefs(BMessage *m, bool changedir)
|
|
832 {
|
|
833 VimRefsMsg rm;
|
|
834 rm.message = m;
|
|
835 rm.changedir = changedir;
|
|
836
|
|
837 write_port(gui.vdcmp, VimMsg::Refs, &rm, sizeof(rm));
|
|
838 // calls ::RefsReceived
|
|
839 }
|
|
840
|
|
841 void
|
|
842 VimApp::MessageReceived(BMessage *m)
|
|
843 {
|
|
844 switch (m->what) {
|
|
845 case 'save':
|
|
846 {
|
|
847 entry_ref refDirectory;
|
|
848 m->FindRef("directory", &refDirectory);
|
|
849 fBrowsedPath.SetTo(&refDirectory);
|
|
850 BString strName;
|
|
851 m->FindString("name", &strName);
|
|
852 fBrowsedPath.Append(strName.String());
|
|
853 }
|
|
854 break;
|
|
855 case 'open':
|
|
856 {
|
|
857 entry_ref ref;
|
|
858 m->FindRef("refs", &ref);
|
|
859 fBrowsedPath.SetTo(&ref);
|
|
860 }
|
|
861 break;
|
|
862 case B_CANCEL:
|
|
863 {
|
|
864 BFilePanel *panel;
|
|
865 m->FindPointer("source", (void**)&panel);
|
|
866 if(fFilePanelSem != -1 && panel == fFilePanel)
|
|
867 {
|
|
868 delete_sem(fFilePanelSem);
|
|
869 fFilePanelSem = -1;
|
|
870 }
|
|
871
|
|
872 }
|
|
873 break;
|
|
874 default:
|
|
875 Inherited::MessageReceived(m);
|
|
876 break;
|
|
877 }
|
|
878 }
|
|
879
|
|
880 bool
|
|
881 VimApp::QuitRequested()
|
|
882 {
|
|
883 (void)Inherited::QuitRequested();
|
|
884 return false;
|
|
885 }
|
|
886
|
|
887 // ---------------- VimWindow ----------------
|
|
888
|
|
889 VimWindow::VimWindow():
|
|
890 BWindow(BRect(40, 40, 150, 150),
|
|
891 "Vim",
|
|
892 B_TITLED_WINDOW,
|
|
893 0,
|
|
894 B_CURRENT_WORKSPACE)
|
|
895
|
|
896 {
|
|
897 init();
|
|
898 }
|
|
899
|
|
900 VimWindow::~VimWindow()
|
|
901 {
|
|
902 if (formView) {
|
|
903 RemoveChild(formView);
|
|
904 delete formView;
|
|
905 }
|
|
906 gui.vimWindow = NULL;
|
|
907 }
|
|
908
|
|
909 void
|
|
910 VimWindow::init()
|
|
911 {
|
|
912 // Attach the VimFormView
|
|
913 formView = new VimFormView(Bounds());
|
|
914 if (formView != NULL) {
|
|
915 AddChild(formView);
|
|
916 }
|
|
917 }
|
|
918
|
|
919 #if 0 // disabled in zeta patch
|
|
920 void
|
|
921 VimWindow::DispatchMessage(BMessage *m, BHandler *h)
|
|
922 {
|
|
923 /*
|
|
924 * Route B_MOUSE_UP messages to MouseUp(), in
|
|
925 * a manner that should be compatible with the
|
|
926 * intended future system behaviour.
|
|
927 */
|
|
928 switch (m->what) {
|
|
929 case B_MOUSE_UP:
|
|
930 // if (!h) h = PreferredHandler();
|
|
931 // gcc isn't happy without this extra set of braces, complains about
|
|
932 // jump to case label crosses init of 'class BView * v'
|
|
933 // richard@whitequeen.com jul 99
|
|
934 {
|
|
935 BView *v = dynamic_cast<BView *>(h);
|
|
936 if (v) {
|
|
937 // m->PrintToStream();
|
|
938 BPoint where;
|
|
939 m->FindPoint("where", &where);
|
|
940 v->MouseUp(where);
|
|
941 } else {
|
|
942 Inherited::DispatchMessage(m, h);
|
|
943 }
|
|
944 }
|
|
945 break;
|
|
946 default:
|
|
947 Inherited::DispatchMessage(m, h);
|
|
948 }
|
|
949 }
|
|
950 #endif
|
|
951
|
|
952 void
|
|
953 VimWindow::WindowActivated(bool active)
|
|
954 {
|
|
955 Inherited::WindowActivated(active);
|
|
956 // the textArea gets the keyboard action
|
|
957 if (active && gui.vimTextArea)
|
|
958 gui.vimTextArea->MakeFocus(true);
|
|
959
|
|
960 struct VimFocusMsg fm;
|
|
961 fm.active = active;
|
|
962
|
|
963 write_port(gui.vdcmp, VimMsg::Focus, &fm, sizeof(fm));
|
|
964 }
|
|
965
|
|
966 bool
|
|
967 VimWindow::QuitRequested()
|
|
968 {
|
|
969 struct VimKeyMsg km;
|
|
970 km.length = 5;
|
|
971 memcpy((char *)km.chars, "\033:qa\r", km.length);
|
|
972 km.csi_escape = false;
|
|
973 write_port(gui.vdcmp, VimMsg::Key, &km, sizeof(km));
|
|
974 return false;
|
|
975 }
|
|
976
|
|
977 // ---------------- VimFormView ----------------
|
|
978
|
|
979 VimFormView::VimFormView(BRect frame):
|
|
980 BView(frame, "VimFormView", B_FOLLOW_ALL_SIDES,
|
|
981 B_WILL_DRAW | B_FRAME_EVENTS),
|
|
982 menuBar(NULL),
|
|
983 #ifdef FEAT_TOOLBAR
|
|
984 toolBar(NULL),
|
|
985 #endif
|
|
986 #ifdef FEAT_GUI_TABLINE
|
|
987 // showingTabLine(false),
|
|
988 tabLine(NULL),
|
|
989 #endif
|
|
990 textArea(NULL)
|
|
991 {
|
|
992 init(frame);
|
|
993 }
|
|
994
|
|
995 VimFormView::~VimFormView()
|
|
996 {
|
|
997 if (menuBar) {
|
|
998 RemoveChild(menuBar);
|
|
999 #ifdef never
|
|
1000 // deleting the menuBar leads to SEGV on exit
|
|
1001 // richard@whitequeen.com Jul 99
|
|
1002 delete menuBar;
|
|
1003 #endif
|
|
1004 }
|
|
1005
|
|
1006 #ifdef FEAT_TOOLBAR
|
|
1007 delete toolBar;
|
|
1008 #endif
|
|
1009
|
|
1010 #ifdef FEAT_GUI_TABLINE
|
|
1011 delete tabLine;
|
|
1012 #endif
|
|
1013
|
|
1014 if (textArea) {
|
|
1015 RemoveChild(textArea);
|
|
1016 delete textArea;
|
|
1017 }
|
|
1018 gui.vimForm = NULL;
|
|
1019 }
|
|
1020
|
|
1021 void
|
|
1022 VimFormView::init(BRect frame)
|
|
1023 {
|
|
1024 menuBar = new BMenuBar(BRect(0,0,-MENUBAR_MARGIN,-MENUBAR_MARGIN),
|
|
1025 "VimMenuBar");
|
|
1026
|
|
1027 AddChild(menuBar);
|
|
1028
|
|
1029 #ifdef FEAT_TOOLBAR
|
|
1030 toolBar = new VimToolbar(BRect(0,0,0,0), "VimToolBar");
|
|
1031 toolBar->PrepareButtonBitmaps();
|
|
1032 AddChild(toolBar);
|
|
1033 #endif
|
|
1034
|
|
1035 #ifdef FEAT_GUI_TABLINE
|
|
1036 tabLine = new VimTabLine(BRect(0,0,0,0));
|
|
1037 // tabLine->PrepareButtonBitmaps();
|
|
1038 AddChild(tabLine);
|
|
1039 #endif
|
|
1040
|
|
1041 BRect remaining = frame;
|
|
1042 textArea = new VimTextAreaView(remaining);
|
|
1043 AddChild(textArea);
|
|
1044 // The textArea will be resized later when menus are added
|
|
1045
|
|
1046 gui.vimForm = this;
|
|
1047 }
|
|
1048
|
|
1049 #ifdef FEAT_TOOLBAR
|
|
1050 float
|
|
1051 VimFormView::ToolbarHeight() const
|
|
1052 {
|
|
1053 return toolBar ? toolBar->ToolbarHeight() : 0.;
|
|
1054 }
|
|
1055 #endif
|
|
1056
|
|
1057 #ifdef FEAT_GUI_TABLINE
|
|
1058 float
|
|
1059 VimFormView::TablineHeight() const
|
|
1060 {
|
|
1061 return (tabLine && IsShowingTabLine()) ? tabLine->TablineHeight() : 0.;
|
|
1062 }
|
|
1063 #endif
|
|
1064
|
|
1065 void
|
|
1066 VimFormView::AllAttached()
|
|
1067 {
|
|
1068 /*
|
|
1069 * Apparently signals are inherited by the created thread -
|
|
1070 * disable the most annoying ones.
|
|
1071 */
|
|
1072 signal(SIGINT, SIG_IGN);
|
|
1073 signal(SIGQUIT, SIG_IGN);
|
|
1074
|
|
1075 if (menuBar && textArea) {
|
|
1076 /*
|
|
1077 * Resize the textArea to fill the space left over by the menu.
|
|
1078 * This is somewhat futile since it will be done again once
|
|
1079 * menus are added to the menu bar.
|
|
1080 */
|
|
1081 BRect remaining = Bounds();
|
|
1082
|
|
1083 #ifdef FEAT_MENU
|
|
1084 remaining.top += MenuHeight();
|
|
1085 menuBar->ResizeTo(remaining.right, remaining.top);
|
|
1086 gui.menu_height = (int) MenuHeight();
|
|
1087 #endif
|
|
1088
|
|
1089 #ifdef FEAT_TOOLBAR
|
|
1090 toolBar->MoveTo(remaining.left, remaining.top);
|
|
1091 toolBar->ResizeTo(remaining.right, ToolbarHeight());
|
|
1092 remaining.top += ToolbarHeight();
|
|
1093 gui.toolbar_height = ToolbarHeight();
|
|
1094 #endif
|
|
1095
|
|
1096 #ifdef FEAT_GUI_TABLINE
|
|
1097 tabLine->MoveTo(remaining.left, remaining.top);
|
|
1098 tabLine->ResizeTo(remaining.right + 1, TablineHeight());
|
|
1099 remaining.top += TablineHeight();
|
|
1100 gui.tabline_height = TablineHeight();
|
|
1101 #endif
|
|
1102
|
|
1103 textArea->ResizeTo(remaining.Width(), remaining.Height());
|
|
1104 textArea->MoveTo(remaining.left, remaining.top);
|
|
1105 }
|
|
1106
|
|
1107
|
|
1108 Inherited::AllAttached();
|
|
1109 }
|
|
1110
|
|
1111 void
|
|
1112 VimFormView::FrameResized(float new_width, float new_height)
|
|
1113 {
|
|
1114 struct VimResizeMsg sm;
|
|
1115 int adjust_h, adjust_w;
|
|
1116
|
|
1117 new_width += 1; // adjust from width to number of pixels occupied
|
|
1118 new_height += 1;
|
|
1119
|
|
1120 sm.width = (int) new_width;
|
|
1121 sm.height = (int) new_height;
|
|
1122 adjust_w = ((int)new_width - gui_get_base_width()) % gui.char_width;
|
|
1123 adjust_h = ((int)new_height - gui_get_base_height()) % gui.char_height;
|
|
1124
|
|
1125 if (adjust_w > 0 || adjust_h > 0) {
|
|
1126 sm.width -= adjust_w;
|
|
1127 sm.height -= adjust_h;
|
|
1128 }
|
|
1129
|
|
1130 write_port(gui.vdcmp, VimMsg::Resize, &sm, sizeof(sm));
|
|
1131 // calls gui_resize_shell(new_width, new_height);
|
|
1132
|
|
1133 return;
|
|
1134
|
|
1135 /*
|
|
1136 * The area below the vertical scrollbar is erased to the colour
|
|
1137 * set with SetViewColor() automatically, because we had set
|
|
1138 * B_WILL_DRAW. Resizing the window tight around the vertical
|
|
1139 * scroll bar also helps to avoid debris.
|
|
1140 */
|
|
1141 }
|
|
1142
|
|
1143 // ---------------- VimTextAreaView ----------------
|
|
1144
|
|
1145 VimTextAreaView::VimTextAreaView(BRect frame):
|
|
1146 BView(frame, "VimTextAreaView", B_FOLLOW_ALL_SIDES,
|
|
1147 #ifdef FEAT_MBYTE_IME
|
|
1148 B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE | B_INPUT_METHOD_AWARE),
|
|
1149 #else
|
|
1150 B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE),
|
|
1151 #endif
|
|
1152 mouseDragEventCount(0)
|
|
1153 {
|
|
1154 #ifdef FEAT_MBYTE_IME
|
|
1155 IMData.messenger = NULL;
|
|
1156 IMData.message = NULL;
|
|
1157 #endif
|
|
1158 init(frame);
|
|
1159 }
|
|
1160
|
|
1161 VimTextAreaView::~VimTextAreaView()
|
|
1162 {
|
|
1163 gui.vimTextArea = NULL;
|
|
1164 }
|
|
1165
|
|
1166 void
|
|
1167 VimTextAreaView::init(BRect frame)
|
|
1168 {
|
|
1169 // set up global var for fast access
|
|
1170 gui.vimTextArea = this;
|
|
1171
|
|
1172 /*
|
|
1173 * Tell the app server not to erase the view: we will
|
|
1174 * fill it in completely by ourselves.
|
|
1175 * (Does this really work? Even if not, it won't harm either.)
|
|
1176 */
|
|
1177 SetViewColor(B_TRANSPARENT_32_BIT);
|
|
1178 #define PEN_WIDTH 1
|
|
1179 SetPenSize(PEN_WIDTH);
|
|
1180 #define W_WIDTH(curwin) 0
|
|
1181 }
|
|
1182
|
|
1183 void
|
|
1184 VimTextAreaView::Draw(BRect updateRect)
|
|
1185 {
|
|
1186 /*
|
|
1187 * XXX Other ports call here:
|
|
1188 * out_flush(); * make sure all output has been processed *
|
|
1189 * but we can't do that, since it involves too much information
|
|
1190 * that is owned by other threads...
|
|
1191 */
|
|
1192
|
|
1193 /*
|
|
1194 * No need to use gui.vimWindow->Lock(): we are locked already.
|
|
1195 * However, it would not hurt.
|
|
1196 */
|
|
1197 rgb_color rgb = GUI_TO_RGB(gui.back_pixel);
|
|
1198 SetLowColor(rgb);
|
|
1199 FillRect(updateRect, B_SOLID_LOW);
|
|
1200 gui_redraw((int) updateRect.left, (int) updateRect.top,
|
|
1201 (int) (updateRect.Width() + PEN_WIDTH), (int) (updateRect.Height() + PEN_WIDTH));
|
|
1202
|
|
1203 // Clear the border areas if needed
|
|
1204 SetLowColor(rgb);
|
|
1205
|
|
1206 if (updateRect.left < FILL_X(0)) // left border
|
|
1207 FillRect(BRect(updateRect.left, updateRect.top,
|
|
1208 FILL_X(0)-PEN_WIDTH, updateRect.bottom), B_SOLID_LOW);
|
|
1209 if (updateRect.top < FILL_Y(0)) // top border
|
|
1210 FillRect(BRect(updateRect.left, updateRect.top,
|
|
1211 updateRect.right, FILL_Y(0)-PEN_WIDTH), B_SOLID_LOW);
|
|
1212 if (updateRect.right >= FILL_X(Columns)) // right border
|
|
1213 FillRect(BRect(FILL_X((int)Columns), updateRect.top,
|
|
1214 updateRect.right, updateRect.bottom), B_SOLID_LOW);
|
|
1215 if (updateRect.bottom >= FILL_Y(Rows)) // bottom border
|
|
1216 FillRect(BRect(updateRect.left, FILL_Y((int)Rows),
|
|
1217 updateRect.right, updateRect.bottom), B_SOLID_LOW);
|
|
1218
|
|
1219 #ifdef FEAT_MBYTE_IME
|
|
1220 DrawIMString();
|
|
1221 #endif
|
|
1222 }
|
|
1223
|
|
1224 void
|
|
1225 VimTextAreaView::KeyDown(const char *bytes, int32 numBytes)
|
|
1226 {
|
|
1227 struct VimKeyMsg km;
|
|
1228 char_u *dest = km.chars;
|
|
1229
|
|
1230 bool canHaveVimModifiers = false;
|
|
1231
|
|
1232 BMessage *msg = Window()->CurrentMessage();
|
|
1233 assert(msg);
|
|
1234 // msg->PrintToStream();
|
|
1235
|
|
1236 /*
|
|
1237 * Convert special keys to Vim codes.
|
|
1238 * I think it is better to do it in the window thread
|
|
1239 * so we use at least a little bit of the potential
|
|
1240 * of our 2 CPUs. Besides, due to the fantastic mapping
|
|
1241 * of special keys to UTF-8, we have quite some work to
|
|
1242 * do...
|
|
1243 * TODO: I'm not quite happy with detection of special
|
|
1244 * keys. Perhaps I should use scan codes after all...
|
|
1245 */
|
|
1246 if (numBytes > 1) {
|
|
1247 // This cannot be a special key
|
|
1248 if (numBytes > KEY_MSG_BUFSIZ)
|
|
1249 numBytes = KEY_MSG_BUFSIZ; // should never happen... ???
|
|
1250 km.length = numBytes;
|
|
1251 memcpy((char *)dest, bytes, numBytes);
|
|
1252 km.csi_escape = true;
|
|
1253 } else {
|
|
1254 int32 scancode = 0;
|
|
1255 msg->FindInt32("key", &scancode);
|
|
1256
|
|
1257 int32 beModifiers = 0;
|
|
1258 msg->FindInt32("modifiers", &beModifiers);
|
|
1259
|
|
1260 char_u string[3];
|
|
1261 int len = 0;
|
|
1262 km.length = 0;
|
|
1263
|
|
1264 /*
|
|
1265 * For normal, printable ASCII characters, don't look them up
|
|
1266 * to check if they might be a special key. They aren't.
|
|
1267 */
|
|
1268 assert(B_BACKSPACE <= 0x20);
|
|
1269 assert(B_DELETE == 0x7F);
|
|
1270 if (((char_u)bytes[0] <= 0x20 || (char_u)bytes[0] == 0x7F) &&
|
|
1271 numBytes == 1) {
|
|
1272 /*
|
|
1273 * Due to the great nature of Be's mapping of special keys,
|
|
1274 * viz. into the range of the control characters,
|
|
1275 * we can only be sure it is *really* a special key if
|
|
1276 * if it is special without using ctrl. So, only if ctrl is
|
|
1277 * used, we need to check it unmodified.
|
|
1278 */
|
|
1279 if (beModifiers & B_CONTROL_KEY) {
|
|
1280 int index = keyMap->normal_map[scancode];
|
|
1281 int newNumBytes = keyMapChars[index];
|
|
1282 char_u *newBytes = (char_u *)&keyMapChars[index + 1];
|
|
1283
|
|
1284 /*
|
|
1285 * Check if still special without the control key.
|
|
1286 * This is needed for BACKSPACE: that key does produce
|
|
1287 * different values with modifiers (DEL).
|
|
1288 * Otherwise we could simply have checked for equality.
|
|
1289 */
|
|
1290 if (newNumBytes != 1 || (*newBytes > 0x20 &&
|
|
1291 *newBytes != 0x7F )) {
|
|
1292 goto notspecial;
|
|
1293 }
|
|
1294 bytes = (char *)newBytes;
|
|
1295 }
|
|
1296 canHaveVimModifiers = true;
|
|
1297
|
|
1298 uint16 beoskey;
|
|
1299 int first, last;
|
|
1300
|
|
1301 /*
|
|
1302 * If numBytes == 0 that probably always indicates a special key.
|
|
1303 * (does not happen yet)
|
|
1304 */
|
|
1305 if (numBytes == 0 || bytes[0] == B_FUNCTION_KEY) {
|
|
1306 beoskey = F(scancode);
|
|
1307 first = FIRST_FUNCTION_KEY;
|
|
1308 last = NUM_SPECIAL_KEYS;
|
|
1309 } else if (*bytes == '\n' && scancode == 0x47) {
|
|
1310 // remap the (non-keypad) ENTER key from \n to \r.
|
|
1311 string[0] = '\r';
|
|
1312 len = 1;
|
|
1313 first = last = 0;
|
|
1314 } else {
|
|
1315 beoskey = K(bytes[0]);
|
|
1316 first = 0;
|
|
1317 last = FIRST_FUNCTION_KEY;
|
|
1318 }
|
|
1319
|
|
1320 for (int i = first; i < last; i++) {
|
|
1321 if (special_keys[i].BeKeys == beoskey) {
|
|
1322 string[0] = CSI;
|
|
1323 string[1] = special_keys[i].vim_code0;
|
|
1324 string[2] = special_keys[i].vim_code1;
|
|
1325 len = 3;
|
|
1326 }
|
|
1327 }
|
|
1328 }
|
|
1329 notspecial:
|
|
1330 if (len == 0) {
|
|
1331 string[0] = bytes[0];
|
|
1332 len = 1;
|
|
1333 }
|
|
1334
|
|
1335 // Special keys (and a few others) may have modifiers
|
|
1336 #if 0
|
|
1337 if (len == 3 ||
|
|
1338 bytes[0] == B_SPACE || bytes[0] == B_TAB ||
|
|
1339 bytes[0] == B_RETURN || bytes[0] == '\r' ||
|
|
1340 bytes[0] == B_ESCAPE)
|
|
1341 #else
|
|
1342 if (canHaveVimModifiers)
|
|
1343 #endif
|
|
1344 {
|
|
1345 int modifiers;
|
|
1346 modifiers = 0;
|
|
1347 if (beModifiers & B_SHIFT_KEY)
|
|
1348 modifiers |= MOD_MASK_SHIFT;
|
|
1349 if (beModifiers & B_CONTROL_KEY)
|
|
1350 modifiers |= MOD_MASK_CTRL;
|
|
1351 if (beModifiers & B_OPTION_KEY)
|
|
1352 modifiers |= MOD_MASK_ALT;
|
|
1353
|
|
1354 /*
|
|
1355 * For some keys a shift modifier is translated into another key
|
|
1356 * code. Do we need to handle the case where len != 1 and
|
|
1357 * string[0] != CSI? (Not for BeOS, since len == 3 implies
|
|
1358 * string[0] == CSI...)
|
|
1359 */
|
|
1360 int key;
|
|
1361 if (string[0] == CSI && len == 3)
|
|
1362 key = TO_SPECIAL(string[1], string[2]);
|
|
1363 else
|
|
1364 key = string[0];
|
|
1365 key = simplify_key(key, &modifiers);
|
|
1366 if (IS_SPECIAL(key))
|
|
1367 {
|
|
1368 string[0] = CSI;
|
|
1369 string[1] = K_SECOND(key);
|
|
1370 string[2] = K_THIRD(key);
|
|
1371 len = 3;
|
|
1372 }
|
|
1373 else
|
|
1374 {
|
|
1375 string[0] = key;
|
|
1376 len = 1;
|
|
1377 }
|
|
1378
|
|
1379 if (modifiers)
|
|
1380 {
|
|
1381 *dest++ = CSI;
|
|
1382 *dest++ = KS_MODIFIER;
|
|
1383 *dest++ = modifiers;
|
|
1384 km.length = 3;
|
|
1385 }
|
|
1386 }
|
|
1387 memcpy((char *)dest, string, len);
|
|
1388 km.length += len;
|
|
1389 km.csi_escape = false;
|
|
1390 }
|
|
1391
|
|
1392 write_port(gui.vdcmp, VimMsg::Key, &km, sizeof(km));
|
|
1393
|
|
1394 /*
|
|
1395 * blank out the pointer if necessary
|
|
1396 */
|
|
1397 if (p_mh && !gui.pointer_hidden)
|
|
1398 {
|
|
1399 guiBlankMouse(true);
|
|
1400 gui.pointer_hidden = TRUE;
|
|
1401 }
|
|
1402 }
|
|
1403 void
|
|
1404 VimTextAreaView::guiSendMouseEvent(
|
|
1405 int button,
|
|
1406 int x,
|
|
1407 int y,
|
|
1408 int repeated_click,
|
|
1409 int_u modifiers)
|
|
1410 {
|
|
1411 VimMouseMsg mm;
|
|
1412
|
|
1413 mm.button = button;
|
|
1414 mm.x = x;
|
|
1415 mm.y = y;
|
|
1416 mm.repeated_click = repeated_click;
|
|
1417 mm.modifiers = modifiers;
|
|
1418
|
|
1419 write_port(gui.vdcmp, VimMsg::Mouse, &mm, sizeof(mm));
|
|
1420 // calls gui_send_mouse_event()
|
|
1421
|
|
1422 /*
|
|
1423 * if our pointer is currently hidden, then we should show it.
|
|
1424 */
|
|
1425 if (gui.pointer_hidden)
|
|
1426 {
|
|
1427 guiBlankMouse(false);
|
|
1428 gui.pointer_hidden = FALSE;
|
|
1429 }
|
|
1430 }
|
|
1431
|
|
1432 void
|
|
1433 VimTextAreaView::guiMouseMoved(
|
|
1434 int x,
|
|
1435 int y)
|
|
1436 {
|
|
1437 VimMouseMovedMsg mm;
|
|
1438
|
|
1439 mm.x = x;
|
|
1440 mm.y = y;
|
|
1441
|
|
1442 write_port(gui.vdcmp, VimMsg::MouseMoved, &mm, sizeof(mm));
|
|
1443
|
|
1444 if (gui.pointer_hidden)
|
|
1445 {
|
|
1446 guiBlankMouse(false);
|
|
1447 gui.pointer_hidden = FALSE;
|
|
1448 }
|
|
1449 }
|
|
1450
|
|
1451 void
|
|
1452 VimTextAreaView::guiBlankMouse(bool should_hide)
|
|
1453 {
|
|
1454 if (should_hide) {
|
|
1455 // gui.vimApp->HideCursor();
|
|
1456 gui.vimApp->ObscureCursor();
|
|
1457 /*
|
|
1458 * ObscureCursor() would even be easier, but then
|
|
1459 * Vim's idea of mouse visibility does not necessarily
|
|
1460 * correspond to reality.
|
|
1461 */
|
|
1462 } else {
|
|
1463 // gui.vimApp->ShowCursor();
|
|
1464 }
|
|
1465 }
|
|
1466
|
|
1467 int_u
|
|
1468 VimTextAreaView::mouseModifiersToVim(int32 beModifiers)
|
|
1469 {
|
|
1470 int_u vim_modifiers = 0x0;
|
|
1471
|
|
1472 if (beModifiers & B_SHIFT_KEY)
|
|
1473 vim_modifiers |= MOUSE_SHIFT;
|
|
1474 if (beModifiers & B_CONTROL_KEY)
|
|
1475 vim_modifiers |= MOUSE_CTRL;
|
|
1476 if (beModifiers & B_OPTION_KEY) // Alt or Meta key
|
|
1477 vim_modifiers |= MOUSE_ALT;
|
|
1478
|
|
1479 return vim_modifiers;
|
|
1480 }
|
|
1481
|
|
1482 void
|
|
1483 VimTextAreaView::MouseDown(BPoint point)
|
|
1484 {
|
|
1485 BMessage *m = Window()->CurrentMessage();
|
|
1486 assert(m);
|
|
1487
|
|
1488 int32 buttons = 0;
|
|
1489 m->FindInt32("buttons", &buttons);
|
|
1490
|
|
1491 int vimButton;
|
|
1492
|
|
1493 if (buttons & B_PRIMARY_MOUSE_BUTTON)
|
|
1494 vimButton = MOUSE_LEFT;
|
|
1495 else if (buttons & B_SECONDARY_MOUSE_BUTTON)
|
|
1496 vimButton = MOUSE_RIGHT;
|
|
1497 else if (buttons & B_TERTIARY_MOUSE_BUTTON)
|
|
1498 vimButton = MOUSE_MIDDLE;
|
|
1499 else
|
|
1500 return; // Unknown button
|
|
1501
|
|
1502 vimMouseButton = 1; // don't care which one
|
|
1503
|
|
1504 // Handle multiple clicks
|
|
1505 int32 clicks = 0;
|
|
1506 m->FindInt32("clicks", &clicks);
|
|
1507
|
|
1508 int32 modifiers = 0;
|
|
1509 m->FindInt32("modifiers", &modifiers);
|
|
1510
|
|
1511 vimMouseModifiers = mouseModifiersToVim(modifiers);
|
|
1512
|
|
1513 guiSendMouseEvent(vimButton, point.x, point.y,
|
|
1514 clicks > 1 /* = repeated_click*/, vimMouseModifiers);
|
|
1515 }
|
|
1516
|
|
1517 void
|
|
1518 VimTextAreaView::MouseUp(BPoint point)
|
|
1519 {
|
|
1520 vimMouseButton = 0;
|
|
1521
|
|
1522 BMessage *m = Window()->CurrentMessage();
|
|
1523 assert(m);
|
|
1524 // m->PrintToStream();
|
|
1525
|
|
1526 int32 modifiers = 0;
|
|
1527 m->FindInt32("modifiers", &modifiers);
|
|
1528
|
|
1529 vimMouseModifiers = mouseModifiersToVim(modifiers);
|
|
1530
|
|
1531 guiSendMouseEvent(MOUSE_RELEASE, point.x, point.y,
|
|
1532 0 /* = repeated_click*/, vimMouseModifiers);
|
|
1533
|
|
1534 Inherited::MouseUp(point);
|
|
1535 }
|
|
1536
|
|
1537 void
|
|
1538 VimTextAreaView::MouseMoved(BPoint point, uint32 transit, const BMessage *message)
|
|
1539 {
|
|
1540 /*
|
|
1541 * if our pointer is currently hidden, then we should show it.
|
|
1542 */
|
|
1543 if (gui.pointer_hidden)
|
|
1544 {
|
|
1545 guiBlankMouse(false);
|
|
1546 gui.pointer_hidden = FALSE;
|
|
1547 }
|
|
1548
|
|
1549 if (!vimMouseButton) { // could also check m->"buttons"
|
|
1550 guiMouseMoved(point.x, point.y);
|
|
1551 return;
|
|
1552 }
|
|
1553
|
|
1554 atomic_add(&mouseDragEventCount, 1);
|
|
1555
|
|
1556 // Don't care much about "transit"
|
|
1557 guiSendMouseEvent(MOUSE_DRAG, point.x, point.y, 0, vimMouseModifiers);
|
|
1558 }
|
|
1559
|
|
1560 void
|
|
1561 VimTextAreaView::MessageReceived(BMessage *m)
|
|
1562 {
|
|
1563 switch (m->what) {
|
|
1564 case 'menu':
|
|
1565 {
|
|
1566 VimMenuMsg mm;
|
|
1567 mm.guiMenu = NULL; // in case no pointer in msg
|
|
1568 m->FindPointer("VimMenu", (void **)&mm.guiMenu);
|
|
1569 write_port(gui.vdcmp, VimMsg::Menu, &mm, sizeof(mm));
|
|
1570 }
|
|
1571 break;
|
|
1572 case B_MOUSE_WHEEL_CHANGED:
|
|
1573 {
|
|
1574 VimScrollBar* scb = curwin->w_scrollbars[1].id;
|
|
1575 float small=0, big=0, dy=0;
|
|
1576 m->FindFloat("be:wheel_delta_y", &dy);
|
|
1577 scb->GetSteps(&small, &big);
|
|
1578 scb->SetValue(scb->Value()+small*dy*3);
|
|
1579 scb->ValueChanged(scb->Value());
|
|
1580 #if 0
|
|
1581 scb = curwin->w_scrollbars[0].id;
|
|
1582 scb->GetSteps(&small, &big);
|
|
1583 scb->SetValue(scb->Value()+small*dy);
|
|
1584 scb->ValueChanged(scb->Value());
|
|
1585 #endif
|
|
1586 }
|
|
1587 break;
|
|
1588 #ifdef FEAT_MBYTE_IME
|
|
1589 case B_INPUT_METHOD_EVENT:
|
|
1590 {
|
|
1591 int32 opcode;
|
|
1592 m->FindInt32("be:opcode", &opcode);
|
|
1593 switch(opcode)
|
|
1594 {
|
|
1595 case B_INPUT_METHOD_STARTED:
|
|
1596 if(!IMData.messenger) delete IMData.messenger;
|
|
1597 IMData.messenger = new BMessenger();
|
|
1598 m->FindMessenger("be:reply_to", IMData.messenger);
|
|
1599 break;
|
|
1600 case B_INPUT_METHOD_CHANGED:
|
|
1601 {
|
|
1602 BString str;
|
|
1603 bool confirmed;
|
|
1604 if(IMData.message) *(IMData.message) = *m;
|
|
1605 else IMData.message = new BMessage(*m);
|
|
1606 DrawIMString();
|
|
1607 m->FindBool("be:confirmed", &confirmed);
|
|
1608 if (confirmed)
|
|
1609 {
|
|
1610 m->FindString("be:string", &str);
|
|
1611 char_u *chars = (char_u*)str.String();
|
|
1612 struct VimKeyMsg km;
|
|
1613 km.csi_escape = true;
|
|
1614 int clen;
|
|
1615 int i = 0;
|
|
1616 while (i < str.Length())
|
|
1617 {
|
|
1618 clen = utf_ptr2len(chars+i);
|
|
1619 memcpy(km.chars, chars+i, clen);
|
|
1620 km.length = clen;
|
|
1621 write_port(gui.vdcmp, VimMsg::Key, &km, sizeof(km));
|
|
1622 i += clen;
|
|
1623 }
|
|
1624 }
|
|
1625 }
|
|
1626 break;
|
|
1627 case B_INPUT_METHOD_LOCATION_REQUEST:
|
|
1628 {
|
|
1629 BMessage msg(B_INPUT_METHOD_EVENT);
|
|
1630 msg.AddInt32("be:opcode", B_INPUT_METHOD_LOCATION_REQUEST);
|
|
1631 msg.AddPoint("be:location_reply", IMData.location);
|
|
1632 msg.AddFloat("be:height_reply", FILL_Y(1));
|
|
1633 IMData.messenger->SendMessage(&msg);
|
|
1634 }
|
|
1635 break;
|
|
1636 case B_INPUT_METHOD_STOPPED:
|
|
1637 delete IMData.messenger;
|
|
1638 delete IMData.message;
|
|
1639 IMData.messenger = NULL;
|
|
1640 IMData.message = NULL;
|
|
1641 break;
|
|
1642 }
|
|
1643 }
|
|
1644 // TODO: sz: break here???
|
|
1645 #endif
|
|
1646 default:
|
|
1647 if (m->WasDropped()) {
|
|
1648 BWindow *w = Window();
|
|
1649 w->DetachCurrentMessage();
|
|
1650 w->Minimize(false);
|
|
1651 VimApp::SendRefs(m, (modifiers() & B_SHIFT_KEY) != 0);
|
|
1652 } else {
|
|
1653 Inherited::MessageReceived(m);
|
|
1654 }
|
|
1655 break;
|
|
1656 }
|
|
1657 }
|
|
1658
|
|
1659 int
|
|
1660 VimTextAreaView::mchInitFont(char_u *name)
|
|
1661 {
|
|
1662 VimFont *newFont = (VimFont *)gui_mch_get_font(name, 1);
|
|
1663 if(newFont != NOFONT) {
|
|
1664 gui.norm_font = (GuiFont)newFont;
|
|
1665 gui_mch_set_font((GuiFont)newFont);
|
|
1666 if (name && STRCMP(name, "*") != 0)
|
|
1667 hl_set_font_name(name);
|
|
1668
|
|
1669 SetDrawingMode(B_OP_COPY);
|
|
1670
|
|
1671 /*
|
|
1672 * Try to load other fonts for bold, italic, and bold-italic.
|
|
1673 * We should also try to work out what font to use for these when they are
|
|
1674 * not specified by X resources, but we don't yet.
|
|
1675 */
|
|
1676 return OK;
|
|
1677 }
|
|
1678 return FAIL;
|
|
1679 }
|
|
1680
|
|
1681 void
|
|
1682 VimTextAreaView::mchDrawString(int row, int col, char_u *s, int len, int flags)
|
|
1683 {
|
|
1684 /*
|
|
1685 * First we must erase the area, because DrawString won't do
|
|
1686 * that for us. XXX Most of the time this is a waste of effort
|
|
1687 * since the bachground has been erased already... DRAW_TRANSP
|
|
1688 * should be set when appropriate!!!
|
|
1689 * (Rectangles include the bottom and right edge)
|
|
1690 */
|
|
1691 if (!(flags & DRAW_TRANSP)) {
|
|
1692 int cells;
|
|
1693 cells = 0;
|
|
1694 for(int i=0; i<len; i++) {
|
|
1695 int cn = utf_ptr2cells((char_u *)(s+i));
|
|
1696 if(cn<4) cells += cn;
|
|
1697 }
|
|
1698
|
|
1699 BRect r(FILL_X(col), FILL_Y(row),
|
|
1700 FILL_X(col + cells) - PEN_WIDTH, FILL_Y(row + 1) - PEN_WIDTH);
|
|
1701 FillRect(r, B_SOLID_LOW);
|
|
1702 }
|
|
1703
|
|
1704 BFont font;
|
|
1705 this->GetFont(&font);
|
|
1706 if(!font.IsFixed())
|
|
1707 {
|
|
1708 char* p = (char*)s;
|
|
1709 int32 clen, lastpos = 0;
|
|
1710 BPoint where;
|
|
1711 int cells;
|
|
1712 while((p - (char*)s) < len) {
|
|
1713 clen = utf_ptr2len((u_char*)p);
|
|
1714 where.Set(TEXT_X(col+lastpos), TEXT_Y(row));
|
|
1715 DrawString(p, clen, where);
|
|
1716 if (flags & DRAW_BOLD) {
|
|
1717 where.x += 1.0;
|
|
1718 SetDrawingMode(B_OP_BLEND);
|
|
1719 DrawString(p, clen, where);
|
|
1720 SetDrawingMode(B_OP_COPY);
|
|
1721 }
|
|
1722 cells = utf_ptr2cells((char_u *)p);
|
|
1723 if(cells<4) lastpos += cells;
|
|
1724 else lastpos++;
|
|
1725 p += clen;
|
|
1726 }
|
|
1727 }
|
|
1728 else
|
|
1729 {
|
|
1730 BPoint where(TEXT_X(col), TEXT_Y(row));
|
|
1731 DrawString((char*)s, len, where);
|
|
1732 if (flags & DRAW_BOLD) {
|
|
1733 where.x += 1.0;
|
|
1734 SetDrawingMode(B_OP_BLEND);
|
|
1735 DrawString((char*)s, len, where);
|
|
1736 SetDrawingMode(B_OP_COPY);
|
|
1737 }
|
|
1738 }
|
|
1739
|
|
1740 if (flags & DRAW_UNDERL) {
|
|
1741 int cells;
|
|
1742 cells = 0;
|
|
1743 for(int i=0; i<len; i++) {
|
|
1744 int cn = utf_ptr2cells((char_u *)(s+i));
|
|
1745 if(cn<4) cells += cn;
|
|
1746 }
|
|
1747
|
|
1748 BPoint start(FILL_X(col), FILL_Y(row + 1) - PEN_WIDTH);
|
|
1749 BPoint end(FILL_X(col + cells) - PEN_WIDTH, start.y);
|
|
1750
|
|
1751 StrokeLine(start, end);
|
|
1752 }
|
|
1753 }
|
|
1754
|
|
1755 void
|
|
1756 VimTextAreaView::mchClearBlock(
|
|
1757 int row1,
|
|
1758 int col1,
|
|
1759 int row2,
|
|
1760 int col2)
|
|
1761 {
|
|
1762 BRect r(FILL_X(col1), FILL_Y(row1),
|
|
1763 FILL_X(col2 + 1) - PEN_WIDTH, FILL_Y(row2 + 1) - PEN_WIDTH);
|
|
1764 gui_mch_set_bg_color(gui.back_pixel);
|
|
1765 FillRect(r, B_SOLID_LOW);
|
|
1766 }
|
|
1767
|
|
1768 void
|
|
1769 VimTextAreaView::mchClearAll()
|
|
1770 {
|
|
1771 gui_mch_set_bg_color(gui.back_pixel);
|
|
1772 FillRect(Bounds(), B_SOLID_LOW);
|
|
1773 }
|
|
1774
|
|
1775 /*
|
|
1776 * mchDeleteLines() Lock()s the window by itself.
|
|
1777 */
|
|
1778 void
|
|
1779 VimTextAreaView::mchDeleteLines(int row, int num_lines)
|
|
1780 {
|
|
1781 BRect source, dest;
|
|
1782 source.left = FILL_X(gui.scroll_region_left);
|
|
1783 source.top = FILL_Y(row + num_lines);
|
|
1784 source.right = FILL_X(gui.scroll_region_right + 1) - PEN_WIDTH;
|
|
1785 source.bottom = FILL_Y(gui.scroll_region_bot + 1) - PEN_WIDTH;
|
|
1786
|
|
1787 dest.left = FILL_X(gui.scroll_region_left);
|
|
1788 dest.top = FILL_Y(row);
|
|
1789 dest.right = FILL_X(gui.scroll_region_right + 1) - PEN_WIDTH;
|
|
1790 dest.bottom = FILL_Y(gui.scroll_region_bot - num_lines + 1) - PEN_WIDTH;
|
|
1791
|
|
1792 if (gui.vimWindow->Lock()) {
|
|
1793 // Clear one column more for when bold has spilled over
|
|
1794 CopyBits(source, dest);
|
|
1795 gui_clear_block(gui.scroll_region_bot - num_lines + 1,
|
|
1796 gui.scroll_region_left,
|
|
1797 gui.scroll_region_bot, gui.scroll_region_right);
|
|
1798
|
|
1799
|
|
1800 gui.vimWindow->Unlock();
|
|
1801 /*
|
|
1802 * The Draw() callback will be called now if some of the source
|
|
1803 * bits were not in the visible region.
|
|
1804 */
|
|
1805 }
|
|
1806 // gui_x11_check_copy_area();
|
|
1807 // }
|
|
1808 }
|
|
1809
|
|
1810 /*
|
|
1811 * mchInsertLines() Lock()s the window by itself.
|
|
1812 */
|
|
1813 void
|
|
1814 VimTextAreaView::mchInsertLines(int row, int num_lines)
|
|
1815 {
|
|
1816 BRect source, dest;
|
|
1817
|
|
1818 // XXX Attempt at a hack:
|
|
1819 gui.vimWindow->UpdateIfNeeded();
|
|
1820 source.left = FILL_X(gui.scroll_region_left);
|
|
1821 source.top = FILL_Y(row);
|
|
1822 source.right = FILL_X(gui.scroll_region_right + 1) - PEN_WIDTH;
|
|
1823 source.bottom = FILL_Y(gui.scroll_region_bot - num_lines + 1) - PEN_WIDTH;
|
|
1824
|
|
1825 dest.left = FILL_X(gui.scroll_region_left);
|
|
1826 dest.top = FILL_Y(row + num_lines);
|
|
1827 dest.right = FILL_X(gui.scroll_region_right + 1) - PEN_WIDTH;
|
|
1828 dest.bottom = FILL_Y(gui.scroll_region_bot + 1) - PEN_WIDTH;
|
|
1829
|
|
1830 if (gui.vimWindow->Lock()) {
|
|
1831 // Clear one column more for when bold has spilled over
|
|
1832 CopyBits(source, dest);
|
|
1833 gui_clear_block(row, gui.scroll_region_left,
|
|
1834 row + num_lines - 1, gui.scroll_region_right);
|
|
1835
|
|
1836 gui.vimWindow->Unlock();
|
|
1837 /*
|
|
1838 * The Draw() callback will be called now if some of the source
|
|
1839 * bits were not in the visible region.
|
|
1840 * However, if we scroll too fast it can't keep up and the
|
|
1841 * update region gets messed up. This seems to be because copying
|
|
1842 * un-Draw()n bits does not generate Draw() calls for the copy...
|
|
1843 * I moved the hack to before the CopyBits() to reduce the
|
|
1844 * amount of additional waiting needed.
|
|
1845 */
|
|
1846
|
|
1847 // gui_x11_check_copy_area();
|
|
1848
|
|
1849 }
|
|
1850 }
|
|
1851
|
|
1852 #ifdef FEAT_MBYTE_IME
|
|
1853 /*
|
|
1854 * DrawIMString draws string with IMData.message.
|
|
1855 */
|
|
1856 void VimTextAreaView::DrawIMString(void)
|
|
1857 {
|
|
1858 static const rgb_color r_highlight = {255, 152, 152, 255},
|
|
1859 b_highlight = {152, 203, 255, 255};
|
|
1860 BString str;
|
|
1861 const char* s;
|
|
1862 int len;
|
|
1863 BMessage* msg = IMData.message;
|
|
1864 if (!msg)
|
|
1865 return;
|
|
1866 gui_redraw_block(IMData.row, 0,
|
|
1867 IMData.row + IMData.count, W_WIDTH(curwin), GUI_MON_NOCLEAR);
|
|
1868 bool confirmed = false;
|
|
1869 msg->FindBool("be:confirmed", &confirmed);
|
|
1870 if (confirmed)
|
|
1871 return;
|
|
1872 rgb_color hcolor = HighColor(), lcolor = LowColor();
|
|
1873 msg->FindString("be:string", &str);
|
|
1874 s = str.String();
|
|
1875 len = str.Length();
|
|
1876 SetHighColor(0, 0, 0);
|
|
1877 IMData.row = gui.row;
|
|
1878 IMData.col = gui.col;
|
|
1879 int32 sel_start = 0, sel_end = 0;
|
|
1880 msg->FindInt32("be:selection", 0, &sel_start);
|
|
1881 msg->FindInt32("be:selection", 1, &sel_end);
|
|
1882 int clen, cn;
|
|
1883 BPoint pos(IMData.col, 0);
|
|
1884 BRect r;
|
|
1885 BPoint where;
|
|
1886 IMData.location = ConvertToScreen(
|
|
1887 BPoint(FILL_X(pos.x), FILL_Y(IMData.row + pos.y)));
|
|
1888 for (int i=0; i<len; i+=clen)
|
|
1889 {
|
|
1890 cn = utf_ptr2cells((char_u *)(s+i));
|
|
1891 clen = utf_ptr2len((char_u *)(s+i));
|
|
1892 if (pos.x + cn > W_WIDTH(curwin))
|
|
1893 {
|
|
1894 pos.y++;
|
|
1895 pos.x = 0;
|
|
1896 }
|
|
1897 if (sel_start<=i && i<sel_end)
|
|
1898 {
|
|
1899 SetLowColor(r_highlight);
|
|
1900 IMData.location = ConvertToScreen(
|
|
1901 BPoint(FILL_X(pos.x), FILL_Y(IMData.row + pos.y)));
|
|
1902 }
|
|
1903 else
|
|
1904 {
|
|
1905 SetLowColor(b_highlight);
|
|
1906 }
|
|
1907 r.Set(FILL_X(pos.x), FILL_Y(IMData.row + pos.y),
|
|
1908 FILL_X(pos.x + cn) - PEN_WIDTH,
|
|
1909 FILL_Y(IMData.row + pos.y + 1) - PEN_WIDTH);
|
|
1910 FillRect(r, B_SOLID_LOW);
|
|
1911 where.Set(TEXT_X(pos.x), TEXT_Y(IMData.row + pos.y));
|
|
1912 DrawString((s+i), clen, where);
|
|
1913 pos.x += cn;
|
|
1914 }
|
|
1915 IMData.count = (int)pos.y;
|
|
1916
|
|
1917 SetHighColor(hcolor);
|
|
1918 SetLowColor(lcolor);
|
|
1919 }
|
|
1920 #endif
|
|
1921 // ---------------- VimScrollBar ----------------
|
|
1922
|
|
1923 /*
|
|
1924 * BUG: XXX
|
|
1925 * It seems that BScrollBar determine their direction not from
|
|
1926 * "posture" but from if they are "tall" or "wide" in shape...
|
|
1927 *
|
|
1928 * Also, place them out of sight, because Vim enables them before
|
|
1929 * they are positioned.
|
|
1930 */
|
|
1931 VimScrollBar::VimScrollBar(scrollbar_T *g, orientation posture):
|
|
1932 BScrollBar(posture == B_HORIZONTAL ? BRect(-100,-100,-10,-90) :
|
|
1933 BRect(-100,-100,-90,-10),
|
|
1934 "vim scrollbar", (BView *)NULL,
|
|
1935 0.0, 10.0, posture),
|
|
1936 ignoreValue(-1),
|
|
1937 scrollEventCount(0)
|
|
1938 {
|
|
1939 gsb = g;
|
|
1940 SetResizingMode(B_FOLLOW_NONE);
|
|
1941 }
|
|
1942
|
|
1943 VimScrollBar::~VimScrollBar()
|
|
1944 {
|
|
1945 }
|
|
1946
|
|
1947 void
|
|
1948 VimScrollBar::ValueChanged(float newValue)
|
|
1949 {
|
|
1950 if (ignoreValue >= 0.0 && newValue == ignoreValue) {
|
|
1951 ignoreValue = -1;
|
|
1952 return;
|
|
1953 }
|
|
1954 ignoreValue = -1;
|
|
1955 /*
|
|
1956 * We want to throttle the amount of scroll messages generated.
|
|
1957 * Normally I presume you won't get a new message before we've
|
|
1958 * handled the previous one, but because we're passing them on this
|
|
1959 * happens very quickly. So instead we keep a counter of how many
|
|
1960 * scroll events there are (or will be) in the VDCMP, and the
|
|
1961 * throttling happens at the receiving end.
|
|
1962 */
|
|
1963 atomic_add(&scrollEventCount, 1);
|
|
1964
|
|
1965 struct VimScrollBarMsg sm;
|
|
1966
|
|
1967 sm.sb = this;
|
|
1968 sm.value = (long) newValue;
|
|
1969 sm.stillDragging = TRUE;
|
|
1970
|
|
1971 write_port(gui.vdcmp, VimMsg::ScrollBar, &sm, sizeof(sm));
|
|
1972
|
|
1973 // calls gui_drag_scrollbar(sb, newValue, TRUE);
|
|
1974 }
|
|
1975
|
|
1976 /*
|
|
1977 * When the mouse goes up, report that scrolling has stopped.
|
|
1978 * MouseUp() is NOT called when the mouse-up occurs outside
|
|
1979 * the window, even though the thumb does move while the mouse
|
|
1980 * is outside... This has some funny effects... XXX
|
|
1981 * So we do special processing when the window de/activates.
|
|
1982 */
|
|
1983 void
|
|
1984 VimScrollBar::MouseUp(BPoint where)
|
|
1985 {
|
|
1986 // BMessage *m = Window()->CurrentMessage();
|
|
1987 // m->PrintToStream();
|
|
1988
|
|
1989 atomic_add(&scrollEventCount, 1);
|
|
1990
|
|
1991 struct VimScrollBarMsg sm;
|
|
1992
|
|
1993 sm.sb = this;
|
|
1994 sm.value = (long) Value();
|
|
1995 sm.stillDragging = FALSE;
|
|
1996
|
|
1997 write_port(gui.vdcmp, VimMsg::ScrollBar, &sm, sizeof(sm));
|
|
1998
|
|
1999 // calls gui_drag_scrollbar(sb, newValue, FALSE);
|
|
2000
|
|
2001 Inherited::MouseUp(where);
|
|
2002 }
|
|
2003
|
|
2004 void
|
|
2005 VimScrollBar::SetValue(float newValue)
|
|
2006 {
|
|
2007 if (newValue == Value())
|
|
2008 return;
|
|
2009
|
|
2010 ignoreValue = newValue;
|
|
2011 Inherited::SetValue(newValue);
|
|
2012 }
|
|
2013
|
|
2014 // ---------------- VimFont ----------------
|
|
2015
|
|
2016 VimFont::VimFont(): BFont()
|
|
2017 {
|
|
2018 init();
|
|
2019 }
|
|
2020
|
|
2021 VimFont::VimFont(const VimFont *rhs): BFont(rhs)
|
|
2022 {
|
|
2023 init();
|
|
2024 }
|
|
2025
|
|
2026 VimFont::VimFont(const BFont *rhs): BFont(rhs)
|
|
2027 {
|
|
2028 init();
|
|
2029 }
|
|
2030
|
|
2031 VimFont::VimFont(const VimFont &rhs): BFont(rhs)
|
|
2032 {
|
|
2033 init();
|
|
2034 }
|
|
2035
|
|
2036 VimFont::~VimFont()
|
|
2037 {
|
|
2038 }
|
|
2039
|
|
2040 void
|
|
2041 VimFont::init()
|
|
2042 {
|
|
2043 next = NULL;
|
|
2044 refcount = 1;
|
|
2045 name = NULL;
|
|
2046 }
|
|
2047
|
|
2048 // ---------------- VimDialog ----------------
|
|
2049
|
|
2050 #if defined(FEAT_GUI_DIALOG)
|
|
2051
|
|
2052 const unsigned int kVimDialogButtonMsg = 'VMDB';
|
|
2053 const unsigned int kVimDialogIconStripeWidth = 30;
|
|
2054 const unsigned int kVimDialogButtonsSpacingX = 9;
|
|
2055 const unsigned int kVimDialogButtonsSpacingY = 4;
|
|
2056 const unsigned int kVimDialogSpacingX = 6;
|
|
2057 const unsigned int kVimDialogSpacingY = 10;
|
|
2058 const unsigned int kVimDialogMinimalWidth = 310;
|
|
2059 const unsigned int kVimDialogMinimalHeight = 75;
|
|
2060 const BRect kDefaultRect =
|
|
2061 BRect(0, 0, kVimDialogMinimalWidth, kVimDialogMinimalHeight);
|
|
2062
|
|
2063 VimDialog::VimDialog(int type, const char *title, const char *message,
|
|
2064 const char *buttons, int dfltbutton, const char *textfield, int ex_cmd)
|
|
2065 : BWindow(kDefaultRect, title, B_TITLED_WINDOW_LOOK, B_MODAL_APP_WINDOW_FEEL,
|
|
2066 B_NOT_CLOSABLE | B_NOT_RESIZABLE |
|
|
2067 B_NOT_ZOOMABLE | B_NOT_MINIMIZABLE | B_ASYNCHRONOUS_CONTROLS)
|
|
2068 , fDialogSem(-1)
|
|
2069 , fDialogValue(dfltbutton)
|
|
2070 , fMessageView(NULL)
|
|
2071 , fInputControl(NULL)
|
|
2072 , fInputValue(textfield)
|
|
2073 {
|
|
2074 // master view
|
|
2075 VimDialog::View* view = new VimDialog::View(Bounds());
|
|
2076 if(view == NULL)
|
|
2077 return;
|
|
2078
|
|
2079 if(title == NULL)
|
|
2080 SetTitle("Vim " VIM_VERSION_MEDIUM);
|
|
2081
|
|
2082 AddChild(view);
|
|
2083
|
|
2084 // icon
|
|
2085 view->InitIcon(type);
|
|
2086
|
|
2087 // buttons
|
|
2088 int32 which = 1;
|
|
2089 float maxButtonWidth = 0;
|
|
2090 float maxButtonHeight = 0;
|
|
2091 float buttonsWidth = 0;
|
|
2092 float buttonsHeight = 0;
|
|
2093 BString strButtons(buttons);
|
|
2094 strButtons.RemoveAll("&");
|
|
2095 do {
|
|
2096 int32 end = strButtons.FindFirst('\n');
|
|
2097 if(end != B_ERROR)
|
|
2098 strButtons.SetByteAt(end, '\0');
|
|
2099
|
|
2100 BButton *button = _CreateButton(which++, strButtons.String());
|
|
2101 view->AddChild(button);
|
|
2102 fButtonsList.AddItem(button);
|
|
2103
|
|
2104 maxButtonWidth = max_c(maxButtonWidth, button->Bounds().Width());
|
|
2105 maxButtonHeight = max_c(maxButtonHeight, button->Bounds().Height());
|
|
2106 buttonsWidth += button->Bounds().Width();
|
|
2107 buttonsHeight += button->Bounds().Height();
|
|
2108
|
|
2109 if(end == B_ERROR)
|
|
2110 break;
|
|
2111
|
|
2112 strButtons.Remove(0, end + 1);
|
|
2113 } while(true);
|
|
2114
|
|
2115 int32 buttonsCount = fButtonsList.CountItems();
|
|
2116 buttonsWidth += kVimDialogButtonsSpacingX * (buttonsCount - 1);
|
|
2117 buttonsHeight += kVimDialogButtonsSpacingY * (buttonsCount - 1);
|
|
2118 float dialogWidth = buttonsWidth + kVimDialogIconStripeWidth +
|
|
2119 kVimDialogSpacingX * 2;
|
|
2120 float dialogHeight = maxButtonHeight + kVimDialogSpacingY * 3;
|
|
2121
|
|
2122 // Check 'v' flag in 'guioptions': vertical button placement.
|
|
2123 bool vertical = (vim_strchr(p_go, GO_VERTICAL) != NULL) ||
|
|
2124 dialogWidth >= gui.vimWindow->Bounds().Width();
|
|
2125 if(vertical) {
|
|
2126 dialogWidth -= buttonsWidth;
|
|
2127 dialogWidth += maxButtonWidth;
|
|
2128 dialogHeight -= maxButtonHeight;
|
|
2129 dialogHeight += buttonsHeight;
|
|
2130 }
|
|
2131
|
|
2132 dialogWidth = max_c(dialogWidth, kVimDialogMinimalWidth);
|
|
2133
|
|
2134 // message view
|
|
2135 BRect rect(0, 0, dialogWidth, 0);
|
|
2136 rect.left += kVimDialogIconStripeWidth + 16 + kVimDialogSpacingX;
|
|
2137 rect.top += kVimDialogSpacingY;
|
|
2138 rect.right -= kVimDialogSpacingX;
|
|
2139 rect.bottom = rect.top;
|
|
2140 fMessageView = new BTextView(rect, "_tv_", rect.OffsetByCopy(B_ORIGIN),
|
|
2141 B_FOLLOW_LEFT | B_FOLLOW_TOP, B_WILL_DRAW);
|
|
2142
|
|
2143 fMessageView->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
|
|
2144 rgb_color textColor = ui_color(B_PANEL_TEXT_COLOR);
|
|
2145 fMessageView->SetFontAndColor(be_plain_font, B_FONT_ALL, &textColor);
|
|
2146 fMessageView->SetText(message);
|
|
2147 fMessageView->MakeEditable(false);
|
|
2148 fMessageView->MakeSelectable(false);
|
|
2149 fMessageView->SetWordWrap(true);
|
|
2150 AddChild(fMessageView);
|
|
2151
|
|
2152 float messageHeight = fMessageView->TextHeight(0, fMessageView->CountLines());
|
|
2153 fMessageView->ResizeBy(0, messageHeight);
|
|
2154 fMessageView->SetTextRect(BRect(0, 0, rect.Width(), messageHeight));
|
|
2155
|
|
2156 dialogHeight += messageHeight;
|
|
2157
|
|
2158 // input view
|
|
2159 if(fInputValue != NULL) {
|
|
2160 rect.top =
|
|
2161 rect.bottom += messageHeight + kVimDialogSpacingY;
|
|
2162 fInputControl = new BTextControl(rect, "_iv_", NULL, fInputValue, NULL,
|
|
2163 B_FOLLOW_LEFT | B_FOLLOW_TOP, B_WILL_DRAW | B_NAVIGABLE | B_PULSE_NEEDED);
|
|
2164 fInputControl->TextView()->SetText(fInputValue);
|
|
2165 fInputControl->TextView()->SetWordWrap(false);
|
|
2166 AddChild(fInputControl);
|
|
2167
|
|
2168 float width = 0.f, height = 0.f;
|
|
2169 fInputControl->GetPreferredSize(&width, &height);
|
|
2170 fInputControl->MakeFocus(true);
|
|
2171
|
|
2172 dialogHeight += height + kVimDialogSpacingY * 1.5;
|
|
2173 }
|
|
2174
|
|
2175 dialogHeight = max_c(dialogHeight, kVimDialogMinimalHeight);
|
|
2176
|
|
2177 ResizeTo(dialogWidth, dialogHeight);
|
|
2178 MoveTo((gui.vimWindow->Bounds().Width() - dialogWidth) / 2,
|
|
2179 (gui.vimWindow->Bounds().Height() - dialogHeight) / 2);
|
|
2180
|
|
2181 // adjust layout of buttons
|
|
2182 float buttonWidth = max_c(maxButtonWidth, rect.Width() * 0.66);
|
|
2183 BPoint origin(dialogWidth, dialogHeight);
|
|
2184 origin.x -= kVimDialogSpacingX + (vertical ? buttonWidth : buttonsWidth);
|
|
2185 origin.y -= kVimDialogSpacingY + (vertical ? buttonsHeight : maxButtonHeight);
|
|
2186
|
|
2187 for(int32 i = 0 ; i < buttonsCount; i++) {
|
|
2188 BButton *button = (BButton*)fButtonsList.ItemAt(i);
|
|
2189 button->MoveTo(origin);
|
|
2190 if(vertical) {
|
|
2191 origin.y += button->Frame().Height() + kVimDialogButtonsSpacingY;
|
|
2192 button->ResizeTo(buttonWidth, button->Frame().Height());
|
|
2193 } else
|
|
2194 origin.x += button->Frame().Width() + kVimDialogButtonsSpacingX;
|
|
2195
|
|
2196 if(dfltbutton == i + 1) {
|
|
2197 button->MakeDefault(true);
|
|
2198 button->MakeFocus(fInputControl == NULL);
|
|
2199 }
|
|
2200 }
|
|
2201 }
|
|
2202
|
|
2203 VimDialog::~VimDialog()
|
|
2204 {
|
|
2205 if(fDialogSem > B_OK)
|
|
2206 delete_sem(fDialogSem);
|
|
2207 }
|
|
2208
|
|
2209 int
|
|
2210 VimDialog::Go()
|
|
2211 {
|
|
2212 fDialogSem = create_sem(0, "VimDialogSem");
|
|
2213 if(fDialogSem < B_OK) {
|
|
2214 Quit();
|
|
2215 return fDialogValue;
|
|
2216 }
|
|
2217
|
|
2218 Show();
|
|
2219
|
|
2220 while(acquire_sem(fDialogSem) == B_INTERRUPTED);
|
|
2221
|
|
2222 int retValue = fDialogValue;
|
|
2223 if(fInputValue != NULL)
|
|
2224 vim_strncpy((char_u*)fInputValue, (char_u*)fInputControl->Text(), IOSIZE - 1);
|
|
2225
|
|
2226 if(Lock())
|
|
2227 Quit();
|
|
2228
|
|
2229 return retValue;
|
|
2230 }
|
|
2231
|
|
2232 void VimDialog::MessageReceived(BMessage *msg)
|
|
2233 {
|
|
2234 int32 which = 0;
|
|
2235 if(msg->what != kVimDialogButtonMsg ||
|
|
2236 msg->FindInt32("which", &which) != B_OK)
|
|
2237 return BWindow::MessageReceived(msg);
|
|
2238
|
|
2239 fDialogValue = which;
|
|
2240 delete_sem(fDialogSem);
|
|
2241 fDialogSem = -1;
|
|
2242 }
|
|
2243
|
|
2244 BButton* VimDialog::_CreateButton(int32 which, const char* label)
|
|
2245 {
|
|
2246 BMessage *message = new BMessage(kVimDialogButtonMsg);
|
|
2247 message->AddInt32("which", which);
|
|
2248
|
|
2249 BRect rect(0, 0, 0, 0);
|
|
2250 BString name;
|
|
2251 name << "_b" << which << "_";
|
|
2252
|
|
2253 BButton* button = new BButton(rect, name.String(), label, message,
|
|
2254 B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM);
|
|
2255
|
|
2256 float width = 0.f, height = 0.f;
|
|
2257 button->GetPreferredSize(&width, &height);
|
|
2258 button->ResizeTo(width, height);
|
|
2259
|
|
2260 return button;
|
|
2261 }
|
|
2262
|
|
2263 VimDialog::View::View(BRect frame)
|
|
2264 : BView(frame, "VimDialogView", B_FOLLOW_ALL_SIDES, B_WILL_DRAW),
|
|
2265 fIconBitmap(NULL)
|
|
2266 {
|
|
2267 SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
|
|
2268 }
|
|
2269
|
|
2270 VimDialog::View::~View()
|
|
2271 {
|
|
2272 delete fIconBitmap;
|
|
2273 }
|
|
2274
|
|
2275 void VimDialog::View::Draw(BRect updateRect)
|
|
2276 {
|
|
2277 BRect stripeRect = Bounds();
|
|
2278 stripeRect.right = kVimDialogIconStripeWidth;
|
|
2279 SetHighColor(tint_color(ViewColor(), B_DARKEN_1_TINT));
|
|
2280 FillRect(stripeRect);
|
|
2281
|
|
2282 if(fIconBitmap == NULL)
|
|
2283 return;
|
|
2284
|
|
2285 SetDrawingMode(B_OP_ALPHA);
|
|
2286 SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_OVERLAY);
|
|
2287 DrawBitmapAsync(fIconBitmap, BPoint(18, 6));
|
|
2288 }
|
|
2289
|
|
2290 void VimDialog::View::InitIcon(int32 type)
|
|
2291 {
|
|
2292 if(type == VIM_GENERIC)
|
|
2293 return;
|
|
2294
|
|
2295 BPath path;
|
|
2296 status_t status = find_directory(B_BEOS_SERVERS_DIRECTORY, &path);
|
|
2297 if(status != B_OK) {
|
|
2298 fprintf(stderr, "Cannot retrieve app info:%s\n", strerror(status));
|
|
2299 return;
|
|
2300 }
|
|
2301
|
|
2302 path.Append("app_server");
|
|
2303
|
|
2304 BFile file(path.Path(), O_RDONLY);
|
|
2305 if(file.InitCheck() != B_OK) {
|
|
2306 fprintf(stderr, "App file assignment failed:%s\n",
|
|
2307 strerror(file.InitCheck()));
|
|
2308 return;
|
|
2309 }
|
|
2310
|
|
2311 BResources resources(&file);
|
|
2312 if(resources.InitCheck() != B_OK) {
|
|
2313 fprintf(stderr, "App server resources assignment failed:%s\n",
|
|
2314 strerror(resources.InitCheck()));
|
|
2315 return;
|
|
2316 }
|
|
2317
|
|
2318 const char *name = "";
|
|
2319 switch(type) {
|
|
2320 case VIM_ERROR: name = "stop"; break;
|
|
2321 case VIM_WARNING: name = "warn"; break;
|
|
2322 case VIM_INFO: name = "info"; break;
|
|
2323 case VIM_QUESTION: name = "idea"; break;
|
|
2324 default: return;
|
|
2325 }
|
|
2326
|
|
2327 int32 iconSize = 32;
|
|
2328 fIconBitmap = new BBitmap(BRect(0, 0, iconSize - 1, iconSize - 1), 0, B_RGBA32);
|
|
2329 if(fIconBitmap == NULL || fIconBitmap->InitCheck() != B_OK) {
|
|
2330 fprintf(stderr, "Icon bitmap allocation failed:%s\n",
|
|
2331 (fIconBitmap == NULL) ? "null" : strerror(fIconBitmap->InitCheck()));
|
|
2332 return;
|
|
2333 }
|
|
2334
|
|
2335 size_t size = 0;
|
|
2336 const uint8* iconData = NULL;
|
|
2337 // try vector icon first?
|
|
2338 iconData = (const uint8*)resources.LoadResource(B_VECTOR_ICON_TYPE, name, &size);
|
|
2339 if(iconData != NULL && BIconUtils::GetVectorIcon(iconData, size, fIconBitmap) == B_OK)
|
|
2340 return;
|
|
2341
|
|
2342 // try bitmap icon now
|
|
2343 iconData = (const uint8*)resources.LoadResource(B_LARGE_ICON_TYPE, name, &size);
|
|
2344 if(iconData == NULL) {
|
|
2345 fprintf(stderr, "Bitmap icon resource not found\n");
|
|
2346 delete fIconBitmap;
|
|
2347 fIconBitmap = NULL;
|
|
2348 return;
|
|
2349 }
|
|
2350
|
|
2351 if(fIconBitmap->ColorSpace() != B_CMAP8)
|
|
2352 BIconUtils::ConvertFromCMAP8(iconData, iconSize, iconSize, iconSize, fIconBitmap);
|
|
2353 }
|
|
2354
|
|
2355 const unsigned int kVimDialogOKButtonMsg = 'FDOK';
|
|
2356 const unsigned int kVimDialogCancelButtonMsg = 'FDCN';
|
|
2357 const unsigned int kVimDialogSizeInputMsg = 'SICH';
|
|
2358 const unsigned int kVimDialogFamilySelectMsg = 'MSFM';
|
|
2359 const unsigned int kVimDialogStyleSelectMsg = 'MSST';
|
|
2360 const unsigned int kVimDialogSizeSelectMsg = 'MSSZ';
|
|
2361
|
|
2362 VimSelectFontDialog::VimSelectFontDialog(font_family* family, font_style* style, float* size)
|
|
2363 : BWindow(kDefaultRect, "Font Selection", B_TITLED_WINDOW_LOOK, B_MODAL_APP_WINDOW_FEEL,
|
|
2364 B_NOT_CLOSABLE | B_NOT_RESIZABLE |
|
|
2365 B_NOT_ZOOMABLE | B_NOT_MINIMIZABLE | B_ASYNCHRONOUS_CONTROLS)
|
|
2366 , fStatus(B_NO_INIT)
|
|
2367 , fDialogSem(-1)
|
|
2368 , fDialogValue(false)
|
|
2369 , fFamily(family)
|
|
2370 , fStyle(style)
|
|
2371 , fSize(size)
|
|
2372 , fFontSize(*size)
|
|
2373 , fPreview(0)
|
|
2374 , fFamiliesList(0)
|
|
2375 , fStylesList(0)
|
|
2376 , fSizesList(0)
|
|
2377 , fSizesInput(0)
|
|
2378 {
|
|
2379 strncpy(fFontFamily, *family, B_FONT_FAMILY_LENGTH);
|
|
2380 strncpy(fFontStyle, *style, B_FONT_STYLE_LENGTH);
|
|
2381
|
|
2382 // "client" area view
|
|
2383 BBox *clientBox = new BBox(Bounds(), B_EMPTY_STRING, B_FOLLOW_ALL_SIDES,
|
|
2384 B_WILL_DRAW | B_FRAME_EVENTS | B_NAVIGABLE_JUMP | B_PULSE_NEEDED,
|
|
2385 B_PLAIN_BORDER);
|
|
2386 AddChild(clientBox);
|
|
2387
|
|
2388 // client view
|
|
2389 BRect RC = clientBox->Bounds();
|
|
2390 RC.InsetBy(kVimDialogSpacingX, kVimDialogSpacingY);
|
|
2391 BRect rc(RC.LeftTop(), RC.LeftTop());
|
|
2392
|
|
2393 // at first create all controls
|
|
2394 fPreview = new BStringView(rc, "preview", "DejaVu Sans Mono");
|
|
2395 clientBox->AddChild(fPreview);
|
|
2396
|
|
2397 BBox* boxDivider = new BBox(rc, B_EMPTY_STRING,
|
|
2398 B_FOLLOW_NONE, B_WILL_DRAW, B_FANCY_BORDER);
|
|
2399 clientBox->AddChild(boxDivider);
|
|
2400
|
|
2401 BStringView *labelFamily = new BStringView(rc, "labelFamily", "Family:");
|
|
2402 clientBox->AddChild(labelFamily);
|
|
2403 labelFamily->ResizeToPreferred();
|
|
2404
|
|
2405 BStringView *labelStyle = new BStringView(rc, "labelStyle", "Style:");
|
|
2406 clientBox->AddChild(labelStyle);
|
|
2407 labelStyle->ResizeToPreferred();
|
|
2408
|
|
2409 BStringView *labelSize = new BStringView(rc, "labelSize", "Size:");
|
|
2410 clientBox->AddChild(labelSize);
|
|
2411 labelSize->ResizeToPreferred();
|
|
2412
|
|
2413 fFamiliesList = new BListView(rc, "listFamily",
|
|
2414 B_SINGLE_SELECTION_LIST, B_FOLLOW_ALL_SIDES);
|
|
2415 BScrollView *scrollFamilies = new BScrollView("scrollFamily",
|
|
2416 fFamiliesList, B_FOLLOW_LEFT_RIGHT, 0, false, true);
|
|
2417 clientBox->AddChild(scrollFamilies);
|
|
2418
|
|
2419 fStylesList= new BListView(rc, "listStyles",
|
|
2420 B_SINGLE_SELECTION_LIST, B_FOLLOW_ALL_SIDES);
|
|
2421 BScrollView *scrollStyles = new BScrollView("scrollStyle",
|
|
2422 fStylesList, B_FOLLOW_LEFT_RIGHT, 0, false, true);
|
|
2423 clientBox->AddChild(scrollStyles);
|
|
2424
|
|
2425 fSizesInput = new BTextControl(rc, "inputSize", NULL, "???",
|
|
2426 new BMessage(kVimDialogSizeInputMsg));
|
|
2427 clientBox->AddChild(fSizesInput);
|
|
2428 fSizesInput->ResizeToPreferred();
|
|
2429
|
|
2430 fSizesList = new BListView(rc, "listSizes",
|
|
2431 B_SINGLE_SELECTION_LIST, B_FOLLOW_ALL_SIDES);
|
|
2432 BScrollView *scrollSizes = new BScrollView("scrollSize",
|
|
2433 fSizesList, B_FOLLOW_LEFT_RIGHT, 0, false, true);
|
|
2434 clientBox->AddChild(scrollSizes);
|
|
2435
|
|
2436 BButton *buttonOK = new BButton(rc, "buttonOK", "OK",
|
|
2437 new BMessage(kVimDialogOKButtonMsg));
|
|
2438 clientBox->AddChild(buttonOK);
|
|
2439 buttonOK->ResizeToPreferred();
|
|
2440
|
|
2441 BButton *buttonCancel = new BButton(rc, "buttonCancel", "Cancel",
|
|
2442 new BMessage(kVimDialogCancelButtonMsg));
|
|
2443 clientBox->AddChild(buttonCancel);
|
|
2444 buttonCancel->ResizeToPreferred();
|
|
2445
|
|
2446 // layout controls
|
|
2447 float lineHeight = labelFamily->Bounds().Height();
|
|
2448 float previewHeight = lineHeight * 3;
|
|
2449 float offsetYLabels = previewHeight + kVimDialogSpacingY;
|
|
2450 float offsetYLists = offsetYLabels + lineHeight + kVimDialogSpacingY / 2;
|
|
2451 float offsetYSizes = offsetYLists + fSizesInput->Bounds().Height() + kVimDialogSpacingY / 2;
|
|
2452 float listsHeight = lineHeight * 9;
|
|
2453 float offsetYButtons = offsetYLists + listsHeight + kVimDialogSpacingY;
|
|
2454 float maxControlsHeight = offsetYButtons + buttonOK->Bounds().Height();
|
|
2455 float familiesWidth = labelFamily->Bounds().Width() * 5;
|
|
2456 float offsetXStyles = familiesWidth + kVimDialogSpacingX;
|
|
2457 float stylesWidth = labelStyle->Bounds().Width() * 4;
|
|
2458 float offsetXSizes = offsetXStyles + stylesWidth + kVimDialogSpacingX;
|
|
2459 float sizesWidth = labelSize->Bounds().Width() * 2;
|
|
2460 float maxControlsWidth = offsetXSizes + sizesWidth;
|
|
2461
|
|
2462 ResizeTo(maxControlsWidth + kVimDialogSpacingX * 2,
|
|
2463 maxControlsHeight + kVimDialogSpacingY * 2);
|
|
2464
|
|
2465 BRect rcVim = gui.vimWindow->Frame();
|
|
2466 MoveTo(rcVim.left + (rcVim.Width() - Frame().Width()) / 2,
|
|
2467 rcVim.top + (rcVim.Height() - Frame().Height()) / 2);
|
|
2468
|
|
2469 fPreview->ResizeTo(maxControlsWidth, previewHeight);
|
|
2470 fPreview->SetAlignment(B_ALIGN_CENTER);
|
|
2471
|
|
2472 boxDivider->MoveBy(0.f, previewHeight + kVimDialogSpacingY / 2);
|
|
2473 boxDivider->ResizeTo(maxControlsWidth, 1.f);
|
|
2474
|
|
2475 labelFamily->MoveBy(0.f, offsetYLabels);
|
|
2476 labelStyle->MoveBy(offsetXStyles, offsetYLabels);
|
|
2477 labelSize->MoveBy(offsetXSizes, offsetYLabels);
|
|
2478
|
|
2479 // text control alignment issues
|
|
2480 float insetX = fSizesInput->TextView()->Bounds().Width() - fSizesInput->Bounds().Width();
|
|
2481 float insetY = fSizesInput->TextView()->Bounds().Width() - fSizesInput->Bounds().Width();
|
|
2482
|
|
2483 scrollFamilies->MoveBy(0.f, offsetYLists);
|
|
2484 scrollStyles->MoveBy(offsetXStyles, offsetYLists);
|
|
2485 fSizesInput->MoveBy(offsetXSizes + insetX / 2, offsetYLists + insetY / 2);
|
|
2486 scrollSizes->MoveBy(offsetXSizes, offsetYSizes);
|
|
2487
|
|
2488 fSizesInput->SetAlignment(B_ALIGN_CENTER, B_ALIGN_CENTER);
|
|
2489
|
|
2490 scrollFamilies->ResizeTo(familiesWidth, listsHeight);
|
|
2491 scrollStyles->ResizeTo(stylesWidth, listsHeight);
|
|
2492 fSizesInput->ResizeTo(sizesWidth, fSizesInput->Bounds().Height());
|
|
2493 scrollSizes->ResizeTo(sizesWidth,
|
|
2494 listsHeight - (offsetYSizes - offsetYLists));
|
|
2495
|
|
2496 buttonOK->MoveBy(maxControlsWidth - buttonOK->Bounds().Width(), offsetYButtons);
|
|
2497 buttonCancel->MoveBy(maxControlsWidth - buttonOK->Bounds().Width()
|
|
2498 - buttonCancel->Bounds().Width() - kVimDialogSpacingX, offsetYButtons);
|
|
2499
|
|
2500 // fill lists
|
|
2501 int selIndex = -1;
|
|
2502 int count = count_font_families();
|
|
2503 for (int i = 0; i < count; i++) {
|
|
2504 font_family family;
|
|
2505 if (get_font_family(i, &family ) == B_OK) {
|
|
2506 fFamiliesList->AddItem(new BStringItem((const char*)family));
|
|
2507 if (strncmp(family, fFontFamily, B_FONT_FAMILY_LENGTH) == 0)
|
|
2508 selIndex = i;
|
|
2509 }
|
|
2510 }
|
|
2511
|
|
2512 if (selIndex >= 0) {
|
|
2513 fFamiliesList->Select(selIndex);
|
|
2514 fFamiliesList->ScrollToSelection();
|
|
2515 }
|
|
2516
|
|
2517 _UpdateFontStyles();
|
|
2518
|
|
2519 selIndex = -1;
|
|
2520 for (int size = 8, index = 0; size <= 18; size++, index++) {
|
|
2521 BString str;
|
|
2522 str << size;
|
|
2523 fSizesList->AddItem(new BStringItem(str));
|
|
2524 if (size == fFontSize)
|
|
2525 selIndex = index;
|
|
2526
|
|
2527 }
|
|
2528
|
|
2529 if (selIndex >= 0) {
|
|
2530 fSizesList->Select(selIndex);
|
|
2531 fSizesList->ScrollToSelection();
|
|
2532 }
|
|
2533
|
|
2534 fFamiliesList->SetSelectionMessage(new BMessage(kVimDialogFamilySelectMsg));
|
|
2535 fStylesList->SetSelectionMessage(new BMessage(kVimDialogStyleSelectMsg));
|
|
2536 fSizesList->SetSelectionMessage(new BMessage(kVimDialogSizeSelectMsg));
|
|
2537 fSizesInput->SetModificationMessage(new BMessage(kVimDialogSizeInputMsg));
|
|
2538
|
|
2539 _UpdateSizeInputPreview();
|
|
2540 _UpdateFontPreview();
|
|
2541
|
|
2542 fStatus = B_OK;
|
|
2543 }
|
|
2544
|
|
2545 VimSelectFontDialog::~VimSelectFontDialog()
|
|
2546 {
|
|
2547 _CleanList(fFamiliesList);
|
|
2548 _CleanList(fStylesList);
|
|
2549 _CleanList(fSizesList);
|
|
2550
|
|
2551 if (fDialogSem > B_OK)
|
|
2552 delete_sem(fDialogSem);
|
|
2553 }
|
|
2554
|
|
2555 void
|
|
2556 VimSelectFontDialog::_CleanList(BListView* list)
|
|
2557 {
|
|
2558 while(0 < list->CountItems())
|
|
2559 delete (dynamic_cast<BStringItem*>(list->RemoveItem((int32)0)));
|
|
2560 }
|
|
2561
|
|
2562 bool
|
|
2563 VimSelectFontDialog::Go()
|
|
2564 {
|
|
2565 if (fStatus != B_OK) {
|
|
2566 Quit();
|
|
2567 return NOFONT;
|
|
2568 }
|
|
2569
|
|
2570 fDialogSem = create_sem(0, "VimFontSelectDialogSem");
|
|
2571 if(fDialogSem < B_OK) {
|
|
2572 Quit();
|
|
2573 return fDialogValue;
|
|
2574 }
|
|
2575
|
|
2576 Show();
|
|
2577
|
|
2578 while(acquire_sem(fDialogSem) == B_INTERRUPTED);
|
|
2579
|
|
2580 bool retValue = fDialogValue;
|
|
2581
|
|
2582 if(Lock())
|
|
2583 Quit();
|
|
2584
|
|
2585 return retValue;
|
|
2586 }
|
|
2587
|
|
2588
|
|
2589 void VimSelectFontDialog::_UpdateFontStyles()
|
|
2590 {
|
|
2591 _CleanList(fStylesList);
|
|
2592
|
|
2593 int32 selIndex = -1;
|
|
2594 int32 count = count_font_styles(fFontFamily);
|
|
2595 for (int32 i = 0; i < count; i++) {
|
|
2596 font_style style;
|
|
2597 uint32 flags = 0;
|
|
2598 if (get_font_style(fFontFamily, i, &style, &flags) == B_OK) {
|
|
2599 fStylesList->AddItem(new BStringItem((const char*)style));
|
|
2600 if (strncmp(style, fFontStyle, B_FONT_STYLE_LENGTH) == 0)
|
|
2601 selIndex = i;
|
|
2602 }
|
|
2603 }
|
|
2604
|
|
2605 if (selIndex >= 0) {
|
|
2606 fStylesList->Select(selIndex);
|
|
2607 fStylesList->ScrollToSelection();
|
|
2608 } else
|
|
2609 fStylesList->Select(0);
|
|
2610 }
|
|
2611
|
|
2612
|
|
2613 void VimSelectFontDialog::_UpdateSizeInputPreview()
|
|
2614 {
|
|
2615 char buf[10] = {0};
|
|
2616 vim_snprintf(buf, sizeof(buf), (char*)"%.0f", fFontSize);
|
|
2617 fSizesInput->SetText(buf);
|
|
2618 }
|
|
2619
|
|
2620
|
|
2621 void VimSelectFontDialog::_UpdateFontPreview()
|
|
2622 {
|
|
2623 BFont font;
|
|
2624 fPreview->GetFont(&font);
|
|
2625 font.SetSize(fFontSize);
|
|
2626 font.SetFamilyAndStyle(fFontFamily, fFontStyle);
|
|
2627 fPreview->SetFont(&font, B_FONT_FAMILY_AND_STYLE | B_FONT_SIZE);
|
|
2628
|
|
2629 BString str;
|
|
2630 str << fFontFamily << " " << fFontStyle << ", " << (int)fFontSize << " pt.";
|
|
2631 fPreview->SetText(str);
|
|
2632 }
|
|
2633
|
|
2634
|
|
2635 bool
|
|
2636 VimSelectFontDialog::_UpdateFromListItem(BListView* list, char* text, int textSize)
|
|
2637 {
|
|
2638 int32 index = list->CurrentSelection();
|
|
2639 if (index < 0)
|
|
2640 return false;
|
|
2641 BStringItem* item = (BStringItem*)list->ItemAt(index);
|
|
2642 if (item == NULL)
|
|
2643 return false;
|
|
2644 strncpy(text, item->Text(), textSize);
|
|
2645 return true;
|
|
2646 }
|
|
2647
|
|
2648
|
|
2649 void VimSelectFontDialog::MessageReceived(BMessage *msg)
|
|
2650 {
|
|
2651 switch (msg->what) {
|
|
2652 case kVimDialogOKButtonMsg:
|
|
2653 strncpy(*fFamily, fFontFamily, B_FONT_FAMILY_LENGTH);
|
|
2654 strncpy(*fStyle, fFontStyle, B_FONT_STYLE_LENGTH);
|
|
2655 *fSize = fFontSize;
|
|
2656 fDialogValue = true;
|
|
2657 case kVimDialogCancelButtonMsg:
|
|
2658 delete_sem(fDialogSem);
|
|
2659 fDialogSem = -1;
|
|
2660 return;
|
|
2661 case B_KEY_UP:
|
|
2662 {
|
|
2663 int32 key = 0;
|
|
2664 if (msg->FindInt32("raw_char", &key) == B_OK
|
|
2665 && key == B_ESCAPE) {
|
|
2666 delete_sem(fDialogSem);
|
|
2667 fDialogSem = -1;
|
|
2668 }
|
|
2669 }
|
|
2670 break;
|
|
2671
|
|
2672 case kVimDialogFamilySelectMsg:
|
|
2673 if (_UpdateFromListItem(fFamiliesList,
|
|
2674 fFontFamily, B_FONT_FAMILY_LENGTH)) {
|
|
2675 _UpdateFontStyles();
|
|
2676 _UpdateFontPreview();
|
|
2677 }
|
|
2678 break;
|
|
2679 case kVimDialogStyleSelectMsg:
|
|
2680 if (_UpdateFromListItem(fStylesList,
|
|
2681 fFontStyle, B_FONT_STYLE_LENGTH))
|
|
2682 _UpdateFontPreview();
|
|
2683 break;
|
|
2684 case kVimDialogSizeSelectMsg:
|
|
2685 {
|
|
2686 char buf[10] = {0};
|
|
2687 if (_UpdateFromListItem(fSizesList, buf, sizeof(buf))) {
|
|
2688 float size = atof(buf);
|
|
2689 if (size > 0.f) {
|
|
2690 fFontSize = size;
|
|
2691 _UpdateSizeInputPreview();
|
|
2692 _UpdateFontPreview();
|
|
2693 }
|
|
2694 }
|
|
2695 }
|
|
2696 break;
|
|
2697 case kVimDialogSizeInputMsg:
|
|
2698 {
|
|
2699 float size = atof(fSizesInput->Text());
|
|
2700 if (size > 0.f) {
|
|
2701 fFontSize = size;
|
|
2702 _UpdateFontPreview();
|
|
2703 }
|
|
2704 }
|
|
2705 break;
|
|
2706 default:
|
|
2707 break;
|
|
2708 }
|
|
2709 return BWindow::MessageReceived(msg);
|
|
2710 }
|
|
2711
|
|
2712 #endif // FEAT_GUI_DIALOG
|
|
2713
|
|
2714 #ifdef FEAT_TOOLBAR
|
|
2715
|
|
2716 // some forward declaration required by toolbar functions...
|
|
2717 static BMessage * MenuMessage(vimmenu_T *menu);
|
|
2718
|
|
2719 VimToolbar::VimToolbar(BRect frame, const char *name) :
|
|
2720 BBox(frame, name, B_FOLLOW_LEFT | B_FOLLOW_TOP, B_WILL_DRAW | B_FRAME_EVENTS, B_PLAIN_BORDER)
|
|
2721 {
|
|
2722 }
|
|
2723
|
|
2724 VimToolbar::~VimToolbar()
|
|
2725 {
|
|
2726 int32 count = fButtonsList.CountItems();
|
|
2727 for(int32 i = 0; i < count; i++)
|
|
2728 delete (BPictureButton*)fButtonsList.ItemAt(i);
|
|
2729 fButtonsList.MakeEmpty();
|
|
2730
|
|
2731 delete normalButtonsBitmap;
|
|
2732 delete grayedButtonsBitmap;
|
|
2733 normalButtonsBitmap = NULL;
|
|
2734 grayedButtonsBitmap = NULL;
|
|
2735 }
|
|
2736
|
|
2737 void
|
|
2738 VimToolbar::AttachedToWindow()
|
|
2739 {
|
|
2740 BBox::AttachedToWindow();
|
|
2741
|
|
2742 SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
|
|
2743 }
|
|
2744
|
|
2745 float
|
|
2746 VimToolbar::ToolbarHeight() const
|
|
2747 {
|
|
2748 float size = NULL == normalButtonsBitmap ? 18. : normalButtonsBitmap->Bounds().Height();
|
|
2749 return size + ToolbarMargin * 2 + ButtonMargin * 2 + 1;
|
|
2750 }
|
|
2751
|
|
2752 bool
|
|
2753 VimToolbar::ModifyBitmapToGrayed(BBitmap *bitmap)
|
|
2754 {
|
|
2755 float height = bitmap->Bounds().Height();
|
|
2756 float width = bitmap->Bounds().Width();
|
|
2757
|
|
2758 rgb_color *bits = (rgb_color*)bitmap->Bits();
|
|
2759 int32 pixels = bitmap->BitsLength() / 4;
|
|
2760 for(int32 i = 0; i < pixels; i++) {
|
|
2761 bits[i].red = bits[i].green =
|
|
2762 bits[i].blue = ((uint32)bits[i].red + bits[i].green + bits[i].blue) / 3;
|
|
2763 bits[i].alpha /= 4;
|
|
2764 }
|
|
2765
|
|
2766 return true;
|
|
2767 }
|
|
2768
|
|
2769 bool
|
|
2770 VimToolbar::PrepareButtonBitmaps()
|
|
2771 {
|
|
2772 // first try to load potentially customized $VIRUNTIME/bitmaps/builtin-tools.png
|
|
2773 normalButtonsBitmap = LoadVimBitmap("builtin-tools.png");
|
|
2774 if(normalButtonsBitmap == NULL)
|
|
2775 // customized not found? dig application resources for "builtin-tools" one
|
|
2776 normalButtonsBitmap = BTranslationUtils::GetBitmap(B_PNG_FORMAT, "builtin-tools");
|
|
2777
|
|
2778 if(normalButtonsBitmap == NULL)
|
|
2779 return false;
|
|
2780
|
|
2781 BMessage archive;
|
|
2782 normalButtonsBitmap->Archive(&archive);
|
|
2783
|
|
2784 grayedButtonsBitmap = new BBitmap(&archive);
|
|
2785 if(grayedButtonsBitmap == NULL)
|
|
2786 return false;
|
|
2787
|
|
2788 // modify grayed bitmap
|
|
2789 ModifyBitmapToGrayed(grayedButtonsBitmap);
|
|
2790
|
|
2791 return true;
|
|
2792 }
|
|
2793
|
|
2794 BBitmap *VimToolbar::LoadVimBitmap(const char* fileName)
|
|
2795 {
|
|
2796 BBitmap *bitmap = NULL;
|
|
2797
|
|
2798 int mustfree = 0;
|
|
2799 char_u* runtimePath = vim_getenv((char_u*)"VIMRUNTIME", &mustfree);
|
|
2800 if(runtimePath != NULL && fileName != NULL) {
|
|
2801 BString strPath((char*)runtimePath);
|
|
2802 strPath << "/bitmaps/" << fileName;
|
|
2803 bitmap = BTranslationUtils::GetBitmap(strPath.String());
|
|
2804 }
|
|
2805
|
|
2806 if(mustfree)
|
|
2807 vim_free(runtimePath);
|
|
2808
|
|
2809 return bitmap;
|
|
2810 }
|
|
2811
|
|
2812 bool
|
|
2813 VimToolbar::GetPictureFromBitmap(BPicture *pictureTo, int32 index, BBitmap *bitmapFrom, bool pressed)
|
|
2814 {
|
|
2815 float size = bitmapFrom->Bounds().Height() + 1.;
|
|
2816
|
|
2817 BView view(BRect(0, 0, size, size), "", 0, 0);
|
|
2818
|
|
2819 AddChild(&view);
|
|
2820 view.BeginPicture(pictureTo);
|
|
2821
|
|
2822 view.SetHighColor(ui_color(B_PANEL_BACKGROUND_COLOR));
|
|
2823 view.FillRect(view.Bounds());
|
|
2824 view.SetDrawingMode(B_OP_OVER);
|
|
2825
|
|
2826 BRect source(0, 0, size - 1, size - 1);
|
|
2827 BRect destination(source);
|
|
2828
|
|
2829 source.OffsetBy(size * index, 0);
|
|
2830 destination.OffsetBy(ButtonMargin, ButtonMargin);
|
|
2831
|
|
2832 view.DrawBitmap(bitmapFrom, source, destination);
|
|
2833
|
|
2834 if(pressed) {
|
|
2835 rgb_color shineColor = ui_color(B_SHINE_COLOR);
|
|
2836 rgb_color shadowColor = ui_color(B_SHADOW_COLOR);
|
|
2837 size += ButtonMargin * 2 - 1;
|
|
2838 view.BeginLineArray(4);
|
|
2839 view.AddLine(BPoint(0, 0), BPoint(size, 0), shadowColor);
|
|
2840 view.AddLine(BPoint(size, 0), BPoint(size, size), shineColor);
|
|
2841 view.AddLine(BPoint(size, size), BPoint(0, size), shineColor);
|
|
2842 view.AddLine(BPoint(0, size), BPoint(0, 0), shadowColor);
|
|
2843 view.EndLineArray();
|
|
2844 }
|
|
2845
|
|
2846 view.EndPicture();
|
|
2847 RemoveChild(&view);
|
|
2848
|
|
2849 return true;
|
|
2850 }
|
|
2851
|
|
2852 bool
|
|
2853 VimToolbar::AddButton(int32 index, vimmenu_T *menu)
|
|
2854 {
|
|
2855 BPictureButton *button = NULL;
|
|
2856 if(!menu_is_separator(menu->name)) {
|
|
2857 float size = normalButtonsBitmap ?
|
|
2858 normalButtonsBitmap->Bounds().Height() + 1. + ButtonMargin * 2 : 18.;
|
|
2859 BRect frame(0, 0, size, size);
|
|
2860 BPicture pictureOn;
|
|
2861 BPicture pictureOff;
|
|
2862 BPicture pictureGray;
|
|
2863
|
|
2864 if(menu->iconfile == NULL && menu->iconidx >= 0 && normalButtonsBitmap) {
|
|
2865 GetPictureFromBitmap(&pictureOn, menu->iconidx, normalButtonsBitmap, true);
|
|
2866 GetPictureFromBitmap(&pictureOff, menu->iconidx, normalButtonsBitmap, false);
|
|
2867 GetPictureFromBitmap(&pictureGray, menu->iconidx, grayedButtonsBitmap, false);
|
|
2868 } else {
|
|
2869
|
|
2870 char_u buffer[MAXPATHL] = {0};
|
|
2871 BBitmap *bitmap = NULL;
|
|
2872
|
|
2873 if(menu->iconfile) {
|
|
2874 gui_find_iconfile(menu->iconfile, buffer, (char*)"png");
|
|
2875 bitmap = BTranslationUtils::GetBitmap((char*)buffer);
|
|
2876 }
|
|
2877
|
|
2878 if(bitmap == NULL && gui_find_bitmap(menu->name, buffer, (char*)"png") == OK)
|
|
2879 bitmap = BTranslationUtils::GetBitmap((char*)buffer);
|
|
2880
|
|
2881 if(bitmap == NULL)
|
|
2882 bitmap = new BBitmap(BRect(0, 0, size, size), B_RGB32);
|
|
2883
|
|
2884 GetPictureFromBitmap(&pictureOn, 0, bitmap, true);
|
|
2885 GetPictureFromBitmap(&pictureOff, 0, bitmap, false);
|
|
2886 ModifyBitmapToGrayed(bitmap);
|
|
2887 GetPictureFromBitmap(&pictureGray, 0, bitmap, false);
|
|
2888
|
|
2889 delete bitmap;
|
|
2890 }
|
|
2891
|
|
2892 button = new BPictureButton(frame, (char*)menu->name,
|
|
2893 &pictureOff, &pictureOn, MenuMessage(menu));
|
|
2894
|
|
2895 button->SetDisabledOn(&pictureGray);
|
|
2896 button->SetDisabledOff(&pictureGray);
|
|
2897
|
|
2898 button->SetTarget(gui.vimTextArea);
|
|
2899
|
|
2900 AddChild(button);
|
|
2901
|
|
2902 menu->button = button;
|
|
2903 }
|
|
2904
|
|
2905 bool result = fButtonsList.AddItem(button, index);
|
|
2906 InvalidateLayout();
|
|
2907 return result;
|
|
2908 }
|
|
2909
|
|
2910 bool
|
|
2911 VimToolbar::RemoveButton(vimmenu_T *menu)
|
|
2912 {
|
|
2913 if(menu->button) {
|
|
2914 if(fButtonsList.RemoveItem(menu->button)) {
|
|
2915 delete menu->button;
|
|
2916 menu->button = NULL;
|
|
2917 }
|
|
2918 }
|
|
2919 }
|
|
2920
|
|
2921 bool
|
|
2922 VimToolbar::GrayButton(vimmenu_T *menu, int grey)
|
|
2923 {
|
|
2924 if(menu->button) {
|
|
2925 int32 index = fButtonsList.IndexOf(menu->button);
|
|
2926 if(index >= 0)
|
|
2927 menu->button->SetEnabled(grey ? false : true);
|
|
2928 }
|
|
2929 }
|
|
2930
|
|
2931 void
|
|
2932 VimToolbar::InvalidateLayout()
|
|
2933 {
|
|
2934 int32 offset = ToolbarMargin;
|
|
2935 int32 count = fButtonsList.CountItems();
|
|
2936 for(int32 i = 0; i < count; i++) {
|
|
2937 BPictureButton *button = (BPictureButton *)fButtonsList.ItemAt(i);
|
|
2938 if(button) {
|
|
2939 button->MoveTo(offset, ToolbarMargin);
|
|
2940 offset += button->Bounds().Width() + ToolbarMargin;
|
|
2941 } else
|
|
2942 offset += ToolbarMargin * 3;
|
|
2943 }
|
|
2944 }
|
|
2945
|
|
2946 #endif /*FEAT_TOOLBAR*/
|
|
2947
|
|
2948 #if defined(FEAT_GUI_TABLINE)
|
|
2949
|
|
2950 float
|
|
2951 VimTabLine::TablineHeight() const
|
|
2952 {
|
|
2953 // float size = NULL == normalButtonsBitmap ? 18. : normalButtonsBitmap->Bounds().Height();
|
|
2954 // return size + ToolbarMargin * 2 + ButtonMargin * 2 + 1;
|
|
2955 return TabHeight(); // + ToolbarMargin;
|
|
2956 }
|
|
2957
|
|
2958 void
|
|
2959 VimTabLine::MouseDown(BPoint point)
|
|
2960 {
|
|
2961 if(!gui_mch_showing_tabline())
|
|
2962 return;
|
|
2963
|
|
2964 BMessage *m = Window()->CurrentMessage();
|
|
2965 assert(m);
|
|
2966
|
|
2967 int32 buttons = 0;
|
|
2968 m->FindInt32("buttons", &buttons);
|
|
2969
|
|
2970 int32 clicks = 0;
|
|
2971 m->FindInt32("clicks", &clicks);
|
|
2972
|
|
2973 int index = 0; // 0 means here - no tab found
|
|
2974 for (int i = 0; i < CountTabs(); i++) {
|
|
2975 if(TabFrame(i).Contains(point)) {
|
|
2976 index = i + 1; // indexes are 1-based
|
|
2977 break;
|
|
2978 }
|
|
2979 }
|
|
2980
|
|
2981 int event = -1;
|
|
2982
|
|
2983 if ((buttons & B_PRIMARY_MOUSE_BUTTON) && clicks > 1)
|
|
2984 // left button double click on - create new tab
|
|
2985 event = TABLINE_MENU_NEW;
|
|
2986
|
|
2987 else if (buttons & B_TERTIARY_MOUSE_BUTTON)
|
|
2988 // middle button click - close the pointed tab
|
|
2989 // or create new one in case empty space
|
|
2990 event = index > 0 ? TABLINE_MENU_CLOSE : TABLINE_MENU_NEW;
|
|
2991
|
|
2992 else if (buttons & B_SECONDARY_MOUSE_BUTTON) {
|
|
2993 // right button click - show context menu
|
|
2994 BPopUpMenu* popUpMenu = new BPopUpMenu("tabLineContextMenu", false, false);
|
|
2995 popUpMenu->AddItem(new BMenuItem(_("Close tabi R"), new BMessage(TABLINE_MENU_CLOSE)));
|
|
2996 popUpMenu->AddItem(new BMenuItem(_("New tab T"), new BMessage(TABLINE_MENU_NEW)));
|
|
2997 popUpMenu->AddItem(new BMenuItem(_("Open tab..."), new BMessage(TABLINE_MENU_OPEN)));
|
|
2998
|
|
2999 ConvertToScreen(&point);
|
|
3000 BMenuItem* item = popUpMenu->Go(point);
|
|
3001 if (item != NULL) {
|
|
3002 event = item->Command();
|
|
3003 }
|
|
3004
|
|
3005 delete popUpMenu;
|
|
3006
|
|
3007 } else {
|
|
3008 // default processing
|
|
3009 BTabView::MouseDown(point);
|
|
3010 return;
|
|
3011 }
|
|
3012
|
|
3013 if (event < 0)
|
|
3014 return;
|
|
3015
|
|
3016 VimTablineMenuMsg tmm;
|
|
3017 tmm.index = index;
|
|
3018 tmm.event = event;
|
|
3019 write_port(gui.vdcmp, VimMsg::TablineMenu, &tmm, sizeof(tmm));
|
|
3020 }
|
|
3021
|
|
3022 void
|
|
3023 VimTabLine::VimTab::Select(BView* owner)
|
|
3024 {
|
|
3025 BTab::Select(owner);
|
|
3026
|
|
3027 VimTabLine *tabLine = gui.vimForm->TabLine();
|
|
3028 if(tabLine != NULL) {
|
|
3029
|
|
3030 int32 i = 0;
|
|
3031 for (; i < tabLine->CountTabs(); i++)
|
|
3032 if(this == tabLine->TabAt(i))
|
|
3033 break;
|
|
3034
|
|
3035 // printf("%d:%d:%s\n", i, tabLine->CountTabs(), tabLine->TabAt(i)->Label());
|
|
3036 if(i < tabLine->CountTabs()) {
|
|
3037 VimTablineMsg tm;
|
|
3038 tm.index = i + 1;
|
|
3039 write_port(gui.vdcmp, VimMsg::Tabline, &tm, sizeof(tm));
|
|
3040 }
|
|
3041 }
|
|
3042 }
|
|
3043
|
|
3044 #endif // defined(FEAT_GUI_TABLINE)
|
|
3045
|
|
3046 // ---------------- ----------------
|
|
3047
|
|
3048 // some global variables
|
|
3049 static char appsig[] = "application/x-vnd.Haiku-Vim-8";
|
|
3050 key_map *keyMap;
|
|
3051 char *keyMapChars;
|
|
3052 int main_exitcode = 127;
|
|
3053
|
|
3054 status_t
|
|
3055 gui_haiku_process_event(bigtime_t timeout)
|
|
3056 {
|
|
3057 struct VimMsg vm;
|
|
3058 int32 what;
|
|
3059 ssize_t size;
|
|
3060
|
|
3061 size = read_port_etc(gui.vdcmp, &what, &vm, sizeof(vm),
|
|
3062 B_TIMEOUT, timeout);
|
|
3063
|
|
3064 if (size >= 0) {
|
|
3065 switch (what) {
|
|
3066 case VimMsg::Key:
|
|
3067 {
|
|
3068 char_u *string = vm.u.Key.chars;
|
|
3069 int len = vm.u.Key.length;
|
|
3070 if (len == 1 && string[0] == Ctrl_chr('C')) {
|
|
3071 trash_input_buf();
|
|
3072 got_int = TRUE;
|
|
3073 }
|
|
3074
|
|
3075 if (vm.u.Key.csi_escape)
|
|
3076 #ifndef FEAT_MBYTE_IME
|
|
3077 {
|
|
3078 int i;
|
|
3079 char_u buf[2];
|
|
3080
|
|
3081 for (i = 0; i < len; ++i)
|
|
3082 {
|
|
3083 add_to_input_buf(string + i, 1);
|
|
3084 if (string[i] == CSI)
|
|
3085 {
|
|
3086 // Turn CSI into K_CSI.
|
|
3087 buf[0] = KS_EXTRA;
|
|
3088 buf[1] = (int)KE_CSI;
|
|
3089 add_to_input_buf(buf, 2);
|
|
3090 }
|
|
3091 }
|
|
3092 }
|
|
3093 #else
|
|
3094 add_to_input_buf_csi(string, len);
|
|
3095 #endif
|
|
3096 else
|
|
3097 add_to_input_buf(string, len);
|
|
3098 }
|
|
3099 break;
|
|
3100 case VimMsg::Resize:
|
|
3101 gui_resize_shell(vm.u.NewSize.width, vm.u.NewSize.height);
|
|
3102 break;
|
|
3103 case VimMsg::ScrollBar:
|
|
3104 {
|
|
3105 /*
|
|
3106 * If loads of scroll messages queue up, use only the last
|
|
3107 * one. Always report when the scrollbar stops dragging.
|
|
3108 * This is not perfect yet anyway: these events are queued
|
|
3109 * yet again, this time in the keyboard input buffer.
|
|
3110 */
|
|
3111 int32 oldCount =
|
|
3112 atomic_add(&vm.u.Scroll.sb->scrollEventCount, -1);
|
|
3113 if (oldCount <= 1 || !vm.u.Scroll.stillDragging)
|
|
3114 gui_drag_scrollbar(vm.u.Scroll.sb->getGsb(),
|
|
3115 vm.u.Scroll.value, vm.u.Scroll.stillDragging);
|
|
3116 }
|
|
3117 break;
|
|
3118 #if defined(FEAT_MENU)
|
|
3119 case VimMsg::Menu:
|
|
3120 gui_menu_cb(vm.u.Menu.guiMenu);
|
|
3121 break;
|
|
3122 #endif
|
|
3123 case VimMsg::Mouse:
|
|
3124 {
|
|
3125 int32 oldCount;
|
|
3126 if (vm.u.Mouse.button == MOUSE_DRAG)
|
|
3127 oldCount =
|
|
3128 atomic_add(&gui.vimTextArea->mouseDragEventCount, -1);
|
|
3129 else
|
|
3130 oldCount = 0;
|
|
3131 if (oldCount <= 1)
|
|
3132 gui_send_mouse_event(vm.u.Mouse.button, vm.u.Mouse.x,
|
|
3133 vm.u.Mouse.y, vm.u.Mouse.repeated_click,
|
|
3134 vm.u.Mouse.modifiers);
|
|
3135 }
|
|
3136 break;
|
|
3137 case VimMsg::MouseMoved:
|
|
3138 {
|
|
3139 gui_mouse_moved(vm.u.MouseMoved.x, vm.u.MouseMoved.y);
|
|
3140 }
|
|
3141 break;
|
|
3142 case VimMsg::Focus:
|
|
3143 gui.in_focus = vm.u.Focus.active;
|
|
3144 // XXX Signal that scrollbar dragging has stopped?
|
|
3145 // This is needed because we don't get a MouseUp if
|
|
3146 // that happens while outside the window... :-(
|
|
3147 if (gui.dragged_sb) {
|
|
3148 gui.dragged_sb = SBAR_NONE;
|
|
3149 }
|
|
3150 // gui_update_cursor(TRUE, FALSE);
|
|
3151 break;
|
|
3152 case VimMsg::Refs:
|
|
3153 ::RefsReceived(vm.u.Refs.message, vm.u.Refs.changedir);
|
|
3154 break;
|
|
3155 case VimMsg::Tabline:
|
|
3156 send_tabline_event(vm.u.Tabline.index);
|
|
3157 break;
|
|
3158 case VimMsg::TablineMenu:
|
|
3159 send_tabline_menu_event(vm.u.TablineMenu.index, vm.u.TablineMenu.event);
|
|
3160 break;
|
|
3161 default:
|
|
3162 // unrecognised message, ignore it
|
|
3163 break;
|
|
3164 }
|
|
3165 }
|
|
3166
|
|
3167 /*
|
|
3168 * If size < B_OK, it is an error code.
|
|
3169 */
|
|
3170 return size;
|
|
3171 }
|
|
3172
|
|
3173 /*
|
|
3174 * Here are some functions to protect access to ScreenLines[] and
|
|
3175 * LineOffset[]. These are used from the window thread to respond
|
|
3176 * to a Draw() callback. When that occurs, the window is already
|
|
3177 * locked by the system.
|
|
3178 *
|
|
3179 * Other code that needs to lock is any code that changes these
|
|
3180 * variables. Other read-only access, or access merely to the
|
|
3181 * contents of the screen buffer, need not be locked.
|
|
3182 *
|
|
3183 * If there is no window, don't call Lock() but do succeed.
|
|
3184 */
|
|
3185
|
|
3186 int
|
|
3187 vim_lock_screen()
|
|
3188 {
|
|
3189 return !gui.vimWindow || gui.vimWindow->Lock();
|
|
3190 }
|
|
3191
|
|
3192 void
|
|
3193 vim_unlock_screen()
|
|
3194 {
|
|
3195 if (gui.vimWindow)
|
|
3196 gui.vimWindow->Unlock();
|
|
3197 }
|
|
3198
|
|
3199 #define RUN_BAPPLICATION_IN_NEW_THREAD 0
|
|
3200
|
|
3201 #if RUN_BAPPLICATION_IN_NEW_THREAD
|
|
3202
|
|
3203 int32
|
|
3204 run_vimapp(void *args)
|
|
3205 {
|
|
3206 VimApp app(appsig);
|
|
3207
|
|
3208 gui.vimApp = &app;
|
|
3209 app.Run(); // Run until Quit() called
|
|
3210
|
|
3211 return 0;
|
|
3212 }
|
|
3213
|
|
3214 #else
|
|
3215
|
|
3216 int32
|
|
3217 call_main(void *args)
|
|
3218 {
|
|
3219 struct MainArgs *ma = (MainArgs *)args;
|
|
3220
|
|
3221 return main(ma->argc, ma->argv);
|
|
3222 }
|
|
3223 #endif
|
|
3224
|
|
3225 /*
|
|
3226 * Parse the GUI related command-line arguments. Any arguments used are
|
|
3227 * deleted from argv, and *argc is decremented accordingly. This is called
|
|
3228 * when vim is started, whether or not the GUI has been started.
|
|
3229 */
|
|
3230 void
|
|
3231 gui_mch_prepare(
|
|
3232 int *argc,
|
|
3233 char **argv)
|
|
3234 {
|
|
3235 /*
|
|
3236 * We don't have any command line arguments for the BeOS GUI yet,
|
|
3237 * but this is an excellent place to create our Application object.
|
|
3238 */
|
|
3239 if (!gui.vimApp) {
|
|
3240 thread_info tinfo;
|
|
3241 get_thread_info(find_thread(NULL), &tinfo);
|
|
3242
|
|
3243 // May need the port very early on to process RefsReceived()
|
|
3244 gui.vdcmp = create_port(B_MAX_PORT_COUNT, "vim VDCMP");
|
|
3245
|
|
3246 #if RUN_BAPPLICATION_IN_NEW_THREAD
|
|
3247 thread_id tid = spawn_thread(run_vimapp, "vim VimApp",
|
|
3248 tinfo.priority, NULL);
|
|
3249 if (tid >= B_OK) {
|
|
3250 resume_thread(tid);
|
|
3251 } else {
|
|
3252 getout(1);
|
|
3253 }
|
|
3254 #else
|
|
3255 MainArgs ma = { *argc, argv };
|
|
3256 thread_id tid = spawn_thread(call_main, "vim main()",
|
|
3257 tinfo.priority, &ma);
|
|
3258 if (tid >= B_OK) {
|
|
3259 VimApp app(appsig);
|
|
3260
|
|
3261 gui.vimApp = &app;
|
|
3262 resume_thread(tid);
|
|
3263 /*
|
|
3264 * This is rather horrible.
|
|
3265 * call_main will call main() again...
|
|
3266 * There will be no infinite recursion since
|
|
3267 * gui.vimApp is set now.
|
|
3268 */
|
|
3269 app.Run(); // Run until Quit() called
|
|
3270 // fprintf(stderr, "app.Run() returned...\n");
|
|
3271 status_t dummy_exitcode;
|
|
3272 (void)wait_for_thread(tid, &dummy_exitcode);
|
|
3273
|
|
3274 /*
|
|
3275 * This path should be the normal one taken to exit Vim.
|
|
3276 * The main() thread calls mch_exit() which calls
|
|
3277 * gui_mch_exit() which terminates its thread.
|
|
3278 */
|
|
3279 exit(main_exitcode);
|
|
3280 }
|
|
3281 #endif
|
|
3282 }
|
|
3283 // Don't fork() when starting the GUI. Spawned threads are not
|
|
3284 // duplicated with a fork(). The result is a mess.
|
|
3285 gui.dofork = FALSE;
|
|
3286 /*
|
|
3287 * XXX Try to determine whether we were started from
|
|
3288 * the Tracker or the terminal.
|
|
3289 * It would be nice to have this work, because the Tracker
|
|
3290 * follows symlinks, so even if you double-click on gvim,
|
|
3291 * when it is a link to vim it will still pass a command name
|
|
3292 * of vim...
|
|
3293 * We try here to see if stdin comes from /dev/null. If so,
|
|
3294 * (or if there is an error, which should never happen) start the GUI.
|
|
3295 * This does the wrong thing for vim - </dev/null, and we're
|
|
3296 * too early to see the command line parsing. Tough.
|
|
3297 * On the other hand, it starts the gui for vim file & which is nice.
|
|
3298 */
|
|
3299 if (!isatty(0)) {
|
|
3300 struct stat stat_stdin, stat_dev_null;
|
|
3301
|
|
3302 if (fstat(0, &stat_stdin) == -1 ||
|
|
3303 stat("/dev/null", &stat_dev_null) == -1 ||
|
|
3304 (stat_stdin.st_dev == stat_dev_null.st_dev &&
|
|
3305 stat_stdin.st_ino == stat_dev_null.st_ino))
|
|
3306 gui.starting = TRUE;
|
|
3307 }
|
|
3308 }
|
|
3309
|
|
3310 /*
|
|
3311 * Check if the GUI can be started. Called before gvimrc is sourced.
|
|
3312 * Return OK or FAIL.
|
|
3313 */
|
|
3314 int
|
|
3315 gui_mch_init_check(void)
|
|
3316 {
|
|
3317 return OK; // TODO: GUI can always be started?
|
|
3318 }
|
|
3319
|
|
3320 /*
|
|
3321 * Initialise the GUI. Create all the windows, set up all the call-backs
|
|
3322 * etc.
|
|
3323 */
|
|
3324 int
|
|
3325 gui_mch_init()
|
|
3326 {
|
|
3327 display_errors();
|
|
3328 gui.def_norm_pixel = RGB(0x00, 0x00, 0x00); // black
|
|
3329 gui.def_back_pixel = RGB(0xFF, 0xFF, 0xFF); // white
|
|
3330 gui.norm_pixel = gui.def_norm_pixel;
|
|
3331 gui.back_pixel = gui.def_back_pixel;
|
|
3332
|
|
3333 gui.scrollbar_width = (int) B_V_SCROLL_BAR_WIDTH;
|
|
3334 gui.scrollbar_height = (int) B_H_SCROLL_BAR_HEIGHT;
|
|
3335 #ifdef FEAT_MENU
|
|
3336 gui.menu_height = 19; // initial guess -
|
|
3337 // correct for my default settings
|
|
3338 #endif
|
|
3339 gui.border_offset = 3; // coordinates are inside window borders
|
|
3340
|
|
3341 if (gui.vdcmp < B_OK)
|
|
3342 return FAIL;
|
|
3343 get_key_map(&keyMap, &keyMapChars);
|
|
3344
|
|
3345 gui.vimWindow = new VimWindow(); // hidden and locked
|
|
3346 if (!gui.vimWindow)
|
|
3347 return FAIL;
|
|
3348
|
|
3349 gui.vimWindow->Run(); // Run() unlocks but does not show
|
|
3350
|
|
3351 // Get the colors from the "Normal" group (set in syntax.c or in a vimrc
|
|
3352 // file)
|
|
3353 set_normal_colors();
|
|
3354
|
|
3355 /*
|
|
3356 * Check that none of the colors are the same as the background color
|
|
3357 */
|
|
3358 gui_check_colors();
|
|
3359
|
|
3360 // Get the colors for the highlight groups (gui_check_colors() might have
|
|
3361 // changed them)
|
|
3362 highlight_gui_started(); // re-init colors and fonts
|
|
3363
|
|
3364 gui_mch_new_colors(); // window must exist for this
|
|
3365
|
|
3366 return OK;
|
|
3367 }
|
|
3368
|
|
3369 /*
|
|
3370 * Called when the foreground or background color has been changed.
|
|
3371 */
|
|
3372 void
|
|
3373 gui_mch_new_colors()
|
|
3374 {
|
|
3375 rgb_color rgb = GUI_TO_RGB(gui.back_pixel);
|
|
3376
|
|
3377 if (gui.vimWindow->Lock()) {
|
|
3378 gui.vimForm->SetViewColor(rgb);
|
|
3379 // Does this not have too much effect for those small rectangles?
|
|
3380 gui.vimForm->Invalidate();
|
|
3381 gui.vimWindow->Unlock();
|
|
3382 }
|
|
3383 }
|
|
3384
|
|
3385 /*
|
|
3386 * Open the GUI window which was created by a call to gui_mch_init().
|
|
3387 */
|
|
3388 int
|
|
3389 gui_mch_open()
|
|
3390 {
|
|
3391 if (gui_win_x != -1 && gui_win_y != -1)
|
|
3392 gui_mch_set_winpos(gui_win_x, gui_win_y);
|
|
3393
|
|
3394 // Actually open the window
|
|
3395 if (gui.vimWindow->Lock()) {
|
|
3396 gui.vimWindow->Show();
|
|
3397 gui.vimWindow->Unlock();
|
|
3398 return OK;
|
|
3399 }
|
|
3400
|
|
3401 return FAIL;
|
|
3402 }
|
|
3403
|
|
3404 void
|
|
3405 gui_mch_exit(int vim_exitcode)
|
|
3406 {
|
|
3407 if (gui.vimWindow) {
|
|
3408 thread_id tid = gui.vimWindow->Thread();
|
|
3409 gui.vimWindow->Lock();
|
|
3410 gui.vimWindow->Quit();
|
|
3411 // Wait until it is truely gone
|
|
3412 int32 exitcode;
|
|
3413 wait_for_thread(tid, &exitcode);
|
|
3414 }
|
|
3415 delete_port(gui.vdcmp);
|
|
3416 #if !RUN_BAPPLICATION_IN_NEW_THREAD
|
|
3417 /*
|
|
3418 * We are in the main() thread - quit the App thread and
|
|
3419 * quit ourselves (passing on the exitcode). Use a global since the
|
|
3420 * value from exit_thread() is only used if wait_for_thread() is
|
|
3421 * called in time (race condition).
|
|
3422 */
|
|
3423 #endif
|
|
3424 if (gui.vimApp) {
|
|
3425 VimTextAreaView::guiBlankMouse(false);
|
|
3426
|
|
3427 main_exitcode = vim_exitcode;
|
|
3428 #if RUN_BAPPLICATION_IN_NEW_THREAD
|
|
3429 thread_id tid = gui.vimApp->Thread();
|
|
3430 int32 exitcode;
|
|
3431 gui.vimApp->Lock();
|
|
3432 gui.vimApp->Quit();
|
|
3433 gui.vimApp->Unlock();
|
|
3434 wait_for_thread(tid, &exitcode);
|
|
3435 #else
|
|
3436 gui.vimApp->Lock();
|
|
3437 gui.vimApp->Quit();
|
|
3438 gui.vimApp->Unlock();
|
|
3439 // suicide
|
|
3440 exit_thread(vim_exitcode);
|
|
3441 #endif
|
|
3442 }
|
|
3443 // If we are somehow still here, let mch_exit() handle things.
|
|
3444 }
|
|
3445
|
|
3446 /*
|
|
3447 * Get the position of the top left corner of the window.
|
|
3448 */
|
|
3449 int
|
|
3450 gui_mch_get_winpos(int *x, int *y)
|
|
3451 {
|
|
3452 if (gui.vimWindow->Lock()) {
|
|
3453 BRect r;
|
|
3454 r = gui.vimWindow->Frame();
|
|
3455 gui.vimWindow->Unlock();
|
|
3456 *x = (int)r.left;
|
|
3457 *y = (int)r.top;
|
|
3458 return OK;
|
|
3459 }
|
|
3460 else
|
|
3461 return FAIL;
|
|
3462 }
|
|
3463
|
|
3464 /*
|
|
3465 * Set the position of the top left corner of the window to the given
|
|
3466 * coordinates.
|
|
3467 */
|
|
3468 void
|
|
3469 gui_mch_set_winpos(int x, int y)
|
|
3470 {
|
|
3471 if (gui.vimWindow->Lock()) {
|
|
3472 gui.vimWindow->MoveTo(x, y);
|
|
3473 gui.vimWindow->Unlock();
|
|
3474 }
|
|
3475 }
|
|
3476
|
|
3477 /*
|
|
3478 * Set the size of the window to the given width and height in pixels.
|
|
3479 */
|
|
3480 void
|
|
3481 gui_mch_set_shellsize(
|
|
3482 int width,
|
|
3483 int height,
|
|
3484 int min_width,
|
|
3485 int min_height,
|
|
3486 int base_width,
|
|
3487 int base_height,
|
|
3488 int direction) // TODO: utilize?
|
|
3489 {
|
|
3490 /*
|
|
3491 * We are basically given the size of the VimForm, if I understand
|
|
3492 * correctly. Since it fills the window completely, this will also
|
|
3493 * be the size of the window.
|
|
3494 */
|
|
3495 if (gui.vimWindow->Lock()) {
|
|
3496 gui.vimWindow->ResizeTo(width - PEN_WIDTH, height - PEN_WIDTH);
|
|
3497
|
|
3498 // set size limits
|
|
3499 float minWidth, maxWidth, minHeight, maxHeight;
|
|
3500
|
|
3501 gui.vimWindow->GetSizeLimits(&minWidth, &maxWidth,
|
|
3502 &minHeight, &maxHeight);
|
|
3503 gui.vimWindow->SetSizeLimits(min_width, maxWidth,
|
|
3504 min_height, maxHeight);
|
|
3505
|
|
3506 /*
|
|
3507 * Set the resizing alignment depending on font size.
|
|
3508 */
|
|
3509 gui.vimWindow->SetWindowAlignment(
|
|
3510 B_PIXEL_ALIGNMENT, // window_alignment mode,
|
|
3511 1, // int32 h,
|
|
3512 0, // int32 hOffset = 0,
|
|
3513 gui.char_width, // int32 width = 0,
|
|
3514 base_width, // int32 widthOffset = 0,
|
|
3515 1, // int32 v = 0,
|
|
3516 0, // int32 vOffset = 0,
|
|
3517 gui.char_height, // int32 height = 0,
|
|
3518 base_height // int32 heightOffset = 0
|
|
3519 );
|
|
3520
|
|
3521 gui.vimWindow->Unlock();
|
|
3522 }
|
|
3523 }
|
|
3524
|
|
3525 void
|
|
3526 gui_mch_get_screen_dimensions(
|
|
3527 int *screen_w,
|
|
3528 int *screen_h)
|
|
3529 {
|
|
3530 BRect frame;
|
|
3531
|
|
3532 {
|
|
3533 BScreen screen(gui.vimWindow);
|
|
3534
|
|
3535 if (screen.IsValid()) {
|
|
3536 frame = screen.Frame();
|
|
3537 } else {
|
|
3538 frame.right = 640;
|
|
3539 frame.bottom = 480;
|
|
3540 }
|
|
3541 }
|
|
3542
|
|
3543 // XXX approximations...
|
|
3544 *screen_w = (int) frame.right - 2 * gui.scrollbar_width - 20;
|
|
3545 *screen_h = (int) frame.bottom - gui.scrollbar_height
|
|
3546 #ifdef FEAT_MENU
|
|
3547 - gui.menu_height
|
|
3548 #endif
|
|
3549 - 30;
|
|
3550 }
|
|
3551
|
|
3552 void
|
|
3553 gui_mch_set_text_area_pos(
|
|
3554 int x,
|
|
3555 int y,
|
|
3556 int w,
|
|
3557 int h)
|
|
3558 {
|
|
3559 if (!gui.vimTextArea)
|
|
3560 return;
|
|
3561
|
|
3562 if (gui.vimWindow->Lock()) {
|
|
3563 gui.vimTextArea->MoveTo(x, y);
|
|
3564 gui.vimTextArea->ResizeTo(w - PEN_WIDTH, h - PEN_WIDTH);
|
|
3565
|
|
3566 /*#ifdef FEAT_GUI_TABLINE
|
|
3567 if(gui.vimForm->TabLine() != NULL) {
|
|
3568 gui.vimForm->TabLine()->ResizeTo(w, gui.vimForm->TablineHeight());
|
|
3569 }
|
|
3570 #endif // FEAT_GUI_TABLINE
|
|
3571
|
|
3572 gui.vimWindow->Unlock();
|
|
3573 }
|
|
3574 }
|
|
3575
|
|
3576
|
|
3577 /*
|
|
3578 * Scrollbar stuff:
|
|
3579 */
|
|
3580
|
|
3581 void
|
|
3582 gui_mch_enable_scrollbar(
|
|
3583 scrollbar_T *sb,
|
|
3584 int flag)
|
|
3585 {
|
|
3586 VimScrollBar *vsb = sb->id;
|
|
3587 if (gui.vimWindow->Lock()) {
|
|
3588 /*
|
|
3589 * This function is supposed to be idempotent, but Show()/Hide()
|
|
3590 * is not. Therefore we test if they are needed.
|
|
3591 */
|
|
3592 if (flag) {
|
|
3593 if (vsb->IsHidden()) {
|
|
3594 vsb->Show();
|
|
3595 }
|
|
3596 } else {
|
|
3597 if (!vsb->IsHidden()) {
|
|
3598 vsb->Hide();
|
|
3599 }
|
|
3600 }
|
|
3601 gui.vimWindow->Unlock();
|
|
3602 }
|
|
3603 }
|
|
3604
|
|
3605 void
|
|
3606 gui_mch_set_scrollbar_thumb(
|
|
3607 scrollbar_T *sb,
|
|
3608 int val,
|
|
3609 int size,
|
|
3610 int max)
|
|
3611 {
|
|
3612 if (gui.vimWindow->Lock()) {
|
|
3613 VimScrollBar *s = sb->id;
|
|
3614 if (max == 0) {
|
|
3615 s->SetValue(0);
|
|
3616 s->SetRange(0.0, 0.0);
|
|
3617 } else {
|
|
3618 s->SetProportion((float)size / (max + 1.0));
|
|
3619 s->SetSteps(1.0, size > 5 ? size - 2 : size);
|
|
3620 #ifndef SCROLL_PAST_END // really only defined in gui.c...
|
|
3621 max = max + 1 - size;
|
|
3622 #endif
|
|
3623 if (max < s->Value()) {
|
|
3624 /*
|
|
3625 * If the new maximum is lower than the current value,
|
|
3626 * setting it would cause the value to be clipped and
|
|
3627 * therefore a ValueChanged() call.
|
|
3628 * We avoid this by setting the value first, because
|
|
3629 * it presumably is <= max.
|
|
3630 */
|
|
3631 s->SetValue(val);
|
|
3632 s->SetRange(0.0, max);
|
|
3633 } else {
|
|
3634 /*
|
|
3635 * In the other case, set the range first, since the
|
|
3636 * new value might be higher than the current max.
|
|
3637 */
|
|
3638 s->SetRange(0.0, max);
|
|
3639 s->SetValue(val);
|
|
3640 }
|
|
3641 }
|
|
3642 gui.vimWindow->Unlock();
|
|
3643 }
|
|
3644 }
|
|
3645
|
|
3646 void
|
|
3647 gui_mch_set_scrollbar_pos(
|
|
3648 scrollbar_T *sb,
|
|
3649 int x,
|
|
3650 int y,
|
|
3651 int w,
|
|
3652 int h)
|
|
3653 {
|
|
3654 if (gui.vimWindow->Lock()) {
|
|
3655 BRect winb = gui.vimWindow->Bounds();
|
|
3656 float vsbx = x, vsby = y;
|
|
3657 VimScrollBar *vsb = sb->id;
|
|
3658 vsb->ResizeTo(w - PEN_WIDTH, h - PEN_WIDTH);
|
|
3659 if(winb.right-(x+w)<w) vsbx = winb.right - (w - PEN_WIDTH);
|
|
3660 vsb->MoveTo(vsbx, vsby);
|
|
3661 gui.vimWindow->Unlock();
|
|
3662 }
|
|
3663 }
|
|
3664
|
|
3665 void
|
|
3666 gui_mch_create_scrollbar(
|
|
3667 scrollbar_T *sb,
|
|
3668 int orient) // SBAR_VERT or SBAR_HORIZ
|
|
3669 {
|
|
3670 orientation posture =
|
|
3671 (orient == SBAR_HORIZ) ? B_HORIZONTAL : B_VERTICAL;
|
|
3672
|
|
3673 VimScrollBar *vsb = sb->id = new VimScrollBar(sb, posture);
|
|
3674 if (gui.vimWindow->Lock()) {
|
|
3675 vsb->SetTarget(gui.vimTextArea);
|
|
3676 vsb->Hide();
|
|
3677 gui.vimForm->AddChild(vsb);
|
|
3678 gui.vimWindow->Unlock();
|
|
3679 }
|
|
3680 }
|
|
3681
|
|
3682 #if defined(FEAT_WINDOWS) || defined(PROTO)
|
|
3683 void
|
|
3684 gui_mch_destroy_scrollbar(
|
|
3685 scrollbar_T *sb)
|
|
3686 {
|
|
3687 if (gui.vimWindow->Lock()) {
|
|
3688 sb->id->RemoveSelf();
|
|
3689 delete sb->id;
|
|
3690 gui.vimWindow->Unlock();
|
|
3691 }
|
|
3692 }
|
|
3693 #endif
|
|
3694
|
|
3695 /*
|
|
3696 * Cursor does not flash
|
|
3697 */
|
|
3698 int
|
|
3699 gui_mch_is_blink_off(void)
|
|
3700 {
|
|
3701 return FALSE;
|
|
3702 }
|
|
3703
|
|
3704 /*
|
|
3705 * Cursor blink functions.
|
|
3706 *
|
|
3707 * This is a simple state machine:
|
|
3708 * BLINK_NONE not blinking at all
|
|
3709 * BLINK_OFF blinking, cursor is not shown
|
|
3710 * BLINK_ON blinking, cursor is shown
|
|
3711 */
|
|
3712
|
|
3713 #define BLINK_NONE 0
|
|
3714 #define BLINK_OFF 1
|
|
3715 #define BLINK_ON 2
|
|
3716
|
|
3717 static int blink_state = BLINK_NONE;
|
|
3718 static long_u blink_waittime = 700;
|
|
3719 static long_u blink_ontime = 400;
|
|
3720 static long_u blink_offtime = 250;
|
|
3721 static int blink_timer = 0;
|
|
3722
|
|
3723 void
|
|
3724 gui_mch_set_blinking(
|
|
3725 long waittime,
|
|
3726 long on,
|
|
3727 long off)
|
|
3728 {
|
|
3729 // TODO
|
|
3730 blink_waittime = waittime;
|
|
3731 blink_ontime = on;
|
|
3732 blink_offtime = off;
|
|
3733 }
|
|
3734
|
|
3735 /*
|
|
3736 * Stop the cursor blinking. Show the cursor if it wasn't shown.
|
|
3737 */
|
|
3738 void
|
|
3739 gui_mch_stop_blink()
|
|
3740 {
|
|
3741 // TODO
|
|
3742 if (blink_timer != 0)
|
|
3743 {
|
|
3744 // XtRemoveTimeOut(blink_timer);
|
|
3745 blink_timer = 0;
|
|
3746 }
|
|
3747 if (blink_state == BLINK_OFF)
|
|
3748 gui_update_cursor(TRUE, FALSE);
|
|
3749 blink_state = BLINK_NONE;
|
|
3750 }
|
|
3751
|
|
3752 /*
|
|
3753 * Start the cursor blinking. If it was already blinking, this restarts the
|
|
3754 * waiting time and shows the cursor.
|
|
3755 */
|
|
3756 void
|
|
3757 gui_mch_start_blink()
|
|
3758 {
|
|
3759 // TODO
|
|
3760 if (blink_timer != 0)
|
|
3761 ;// XtRemoveTimeOut(blink_timer);
|
|
3762 // Only switch blinking on if none of the times is zero
|
|
3763 if (blink_waittime && blink_ontime && blink_offtime && gui.in_focus)
|
|
3764 {
|
|
3765 blink_timer = 1; // XtAppAddTimeOut(app_context, blink_waittime,
|
|
3766 blink_state = BLINK_ON;
|
|
3767 gui_update_cursor(TRUE, FALSE);
|
|
3768 }
|
|
3769 }
|
|
3770
|
|
3771 /*
|
|
3772 * Initialise vim to use the font with the given name. Return FAIL if the font
|
|
3773 * could not be loaded, OK otherwise.
|
|
3774 */
|
|
3775 int
|
|
3776 gui_mch_init_font(
|
|
3777 char_u *font_name,
|
|
3778 int fontset)
|
|
3779 {
|
|
3780 if (gui.vimWindow->Lock())
|
|
3781 {
|
|
3782 int rc = gui.vimTextArea->mchInitFont(font_name);
|
|
3783 gui.vimWindow->Unlock();
|
|
3784
|
|
3785 return rc;
|
|
3786 }
|
|
3787
|
|
3788 return FAIL;
|
|
3789 }
|
|
3790
|
|
3791
|
|
3792 int
|
|
3793 gui_mch_adjust_charsize()
|
|
3794 {
|
|
3795 return FAIL;
|
|
3796 }
|
|
3797
|
|
3798
|
|
3799 int
|
|
3800 gui_mch_font_dialog(font_family* family, font_style* style, float* size)
|
|
3801 {
|
|
3802 #if defined(FEAT_GUI_DIALOG)
|
|
3803 // gui.vimWindow->Unlock();
|
|
3804 VimSelectFontDialog *dialog = new VimSelectFontDialog(family, style, size);
|
|
3805 return dialog->Go();
|
|
3806 #else
|
|
3807 return NOFONT;
|
|
3808 #endif // FEAT_GUI_DIALOG
|
|
3809 }
|
|
3810
|
|
3811
|
|
3812 GuiFont
|
|
3813 gui_mch_get_font(
|
|
3814 char_u *name,
|
|
3815 int giveErrorIfMissing)
|
|
3816 {
|
|
3817 static VimFont *fontList = NULL;
|
|
3818
|
|
3819 if (!gui.in_use) // can't do this when GUI not running
|
|
3820 return NOFONT;
|
|
3821
|
|
3822 // storage for locally modified name;
|
|
3823 const int buff_size = B_FONT_FAMILY_LENGTH + B_FONT_STYLE_LENGTH + 20;
|
|
3824 static char font_name[buff_size] = {0};
|
|
3825 font_family family = {0};
|
|
3826 font_style style = {0};
|
|
3827 float size = 0.f;
|
|
3828
|
|
3829 if (name == 0 && be_fixed_font == 0) {
|
|
3830 if(giveErrorIfMissing)
|
|
3831 semsg(_(e_font), name);
|
|
3832 return NOFONT;
|
|
3833 }
|
|
3834
|
|
3835 bool useSelectGUI = false;
|
|
3836 if (name != NULL)
|
|
3837 if (STRCMP(name, "*") == 0) {
|
|
3838 useSelectGUI = true;
|
|
3839 STRNCPY(font_name, hl_get_font_name(), buff_size);
|
|
3840 } else
|
|
3841 STRNCPY(font_name, name, buff_size);
|
|
3842
|
|
3843 if (font_name[0] == 0) {
|
|
3844 be_fixed_font->GetFamilyAndStyle(&family, &style);
|
|
3845 size = be_fixed_font->Size();
|
|
3846 vim_snprintf(font_name, buff_size,
|
|
3847 (char*)"%s/%s/%.0f", family, style, size);
|
|
3848 }
|
|
3849
|
|
3850 // replace underscores with spaces
|
|
3851 char* end = 0;
|
|
3852 while (end = strchr((char *)font_name, '_'))
|
|
3853 *end = ' ';
|
|
3854
|
|
3855 // store the name before strtok corrupt the buffer ;-)
|
|
3856 static char buff[buff_size] = {0};
|
|
3857 STRNCPY(buff, font_name, buff_size);
|
|
3858 STRNCPY(family, strtok(buff, "/\0"), B_FONT_FAMILY_LENGTH);
|
|
3859 char* style_s = strtok(0, "/\0");
|
|
3860 if (style_s != 0)
|
|
3861 STRNCPY(style, style_s, B_FONT_STYLE_LENGTH);
|
|
3862 size = atof((style_s != 0) ? strtok(0, "/\0") : "0");
|
|
3863
|
|
3864 if (useSelectGUI) {
|
|
3865 if(gui_mch_font_dialog(&family, &style, &size) == NOFONT)
|
|
3866 return FAIL;
|
|
3867 // compose for further processing
|
|
3868 vim_snprintf(font_name, buff_size,
|
|
3869 (char*)"%s/%s/%.0f", family, style, size);
|
|
3870 hl_set_font_name((char_u*)font_name);
|
|
3871
|
|
3872 // Set guifont to the name of the selected font.
|
|
3873 char_u* new_p_guifont = alloc(STRLEN(font_name) + 1);
|
|
3874 if (new_p_guifont != NULL) {
|
|
3875 STRCPY(new_p_guifont, font_name);
|
|
3876 vim_free(p_guifont);
|
|
3877 p_guifont = new_p_guifont;
|
|
3878 // Replace spaces in the font name with underscores.
|
|
3879 for ( ; *new_p_guifont; ++new_p_guifont)
|
|
3880 if (*new_p_guifont == ' ')
|
|
3881 *new_p_guifont = '_';
|
|
3882 }
|
|
3883 }
|
|
3884
|
|
3885 VimFont *flp;
|
|
3886 for (flp = fontList; flp; flp = flp->next) {
|
|
3887 if (STRCMP(font_name, flp->name) == 0) {
|
|
3888 flp->refcount++;
|
|
3889 return (GuiFont)flp;
|
|
3890 }
|
|
3891 }
|
|
3892
|
|
3893 VimFont *font = new VimFont();
|
|
3894 font->name = vim_strsave((char_u*)font_name);
|
|
3895
|
|
3896 if(count_font_styles(family) <= 0) {
|
|
3897 if (giveErrorIfMissing)
|
|
3898 semsg(_(e_font), font->name);
|
|
3899 delete font;
|
|
3900 return NOFONT;
|
|
3901 }
|
|
3902
|
|
3903 // Remember font in the static list for later use
|
|
3904 font->next = fontList;
|
|
3905 fontList = font;
|
|
3906
|
|
3907 font->SetFamilyAndStyle(family, style);
|
|
3908 if(size > 0.f)
|
|
3909 font->SetSize(size);
|
|
3910
|
|
3911 font->SetSpacing(B_FIXED_SPACING);
|
|
3912 font->SetEncoding(B_UNICODE_UTF8);
|
|
3913
|
|
3914 return (GuiFont)font;
|
|
3915 }
|
|
3916
|
|
3917 /*
|
|
3918 * Set the current text font.
|
|
3919 */
|
|
3920 void
|
|
3921 gui_mch_set_font(
|
|
3922 GuiFont font)
|
|
3923 {
|
|
3924 if (gui.vimWindow->Lock()) {
|
|
3925 VimFont *vf = (VimFont *)font;
|
|
3926
|
|
3927 gui.vimTextArea->SetFont(vf);
|
|
3928
|
|
3929 gui.char_width = (int) vf->StringWidth("n");
|
|
3930 font_height fh;
|
|
3931 vf->GetHeight(&fh);
|
|
3932 gui.char_height = (int)(fh.ascent + 0.9999)
|
|
3933 + (int)(fh.descent + 0.9999) + (int)(fh.leading + 0.9999);
|
|
3934 gui.char_ascent = (int)(fh.ascent + 0.9999);
|
|
3935
|
|
3936 gui.vimWindow->Unlock();
|
|
3937 }
|
|
3938 }
|
|
3939
|
|
3940 // XXX TODO This is apparently never called...
|
|
3941 void
|
|
3942 gui_mch_free_font(
|
|
3943 GuiFont font)
|
|
3944 {
|
|
3945 if(font == NOFONT)
|
|
3946 return;
|
|
3947 VimFont *f = (VimFont *)font;
|
|
3948 if (--f->refcount <= 0) {
|
|
3949 if (f->refcount < 0)
|
|
3950 fprintf(stderr, "VimFont: refcount < 0\n");
|
|
3951 delete f;
|
|
3952 }
|
|
3953 }
|
|
3954
|
|
3955 char_u *
|
|
3956 gui_mch_get_fontname(GuiFont font, char_u *name)
|
|
3957 {
|
|
3958 if (name == NULL)
|
|
3959 return NULL;
|
|
3960 return vim_strsave(name);
|
|
3961 }
|
|
3962
|
|
3963 /*
|
|
3964 * Adjust gui.char_height (after 'linespace' was changed).
|
|
3965 */
|
|
3966 int
|
|
3967 gui_mch_adjust_charheight()
|
|
3968 {
|
|
3969
|
|
3970 // TODO: linespace support?
|
|
3971
|
|
3972 // #ifdef FEAT_XFONTSET
|
|
3973 // if (gui.fontset != NOFONTSET)
|
|
3974 // {
|
|
3975 // gui.char_height = fontset_height((XFontSet)gui.fontset) + p_linespace;
|
|
3976 // gui.char_ascent = fontset_ascent((XFontSet)gui.fontset)
|
|
3977 // + p_linespace / 2;
|
|
3978 // }
|
|
3979 // else
|
|
3980 // #endif
|
|
3981 {
|
|
3982 VimFont *font = (VimFont *)gui.norm_font;
|
|
3983 font_height fh = {0};
|
|
3984 font->GetHeight(&fh);
|
|
3985 gui.char_height = (int)(fh.ascent + fh.descent + 0.5) + p_linespace;
|
|
3986 gui.char_ascent = (int)(fh.ascent + 0.5) + p_linespace / 2;
|
|
3987 }
|
|
3988 return OK;
|
|
3989 }
|
|
3990
|
|
3991 /*
|
|
3992 * Display the saved error message(s).
|
|
3993 */
|
|
3994 #ifdef USE_MCH_ERRMSG
|
|
3995 void
|
|
3996 display_errors(void)
|
|
3997 {
|
|
3998 char *p;
|
|
3999 char_u pError[256];
|
|
4000
|
|
4001 if (error_ga.ga_data == NULL)
|
|
4002 return;
|
|
4003
|
|
4004 // avoid putting up a message box with blanks only
|
|
4005 for (p = (char *)error_ga.ga_data; *p; ++p)
|
|
4006 if (!isspace(*p))
|
|
4007 {
|
|
4008 if (STRLEN(p) > 255)
|
|
4009 pError[0] = 255;
|
|
4010 else
|
|
4011 pError[0] = STRLEN(p);
|
|
4012
|
|
4013 STRNCPY(&pError[1], p, pError[0]);
|
|
4014 // ParamText(pError, nil, nil, nil);
|
|
4015 // Alert(128, nil);
|
|
4016 break;
|
|
4017 // TODO: handled message longer than 256 chars
|
|
4018 // use auto-sizeable alert
|
|
4019 // or dialog with scrollbars (TextEdit zone)
|
|
4020 }
|
|
4021 ga_clear(&error_ga);
|
|
4022 }
|
|
4023 #endif
|
|
4024
|
|
4025 void
|
|
4026 gui_mch_getmouse(int *x, int *y)
|
|
4027 {
|
|
4028 fprintf(stderr, "gui_mch_getmouse");
|
|
4029
|
|
4030 /*int rootx, rooty, winx, winy;
|
|
4031 Window root, child;
|
|
4032 unsigned int mask;
|
|
4033
|
|
4034 if (gui.wid && XQueryPointer(gui.dpy, gui.wid, &root, &child,
|
|
4035 &rootx, &rooty, &winx, &winy, &mask)) {
|
|
4036 *x = winx;
|
|
4037 *y = winy;
|
|
4038 } else*/ {
|
|
4039 *x = -1;
|
|
4040 *y = -1;
|
|
4041 }
|
|
4042 }
|
|
4043
|
|
4044 void
|
|
4045 gui_mch_mousehide(int hide)
|
|
4046 {
|
|
4047 fprintf(stderr, "gui_mch_getmouse");
|
|
4048 // TODO
|
|
4049 }
|
|
4050
|
|
4051 static int
|
|
4052 hex_digit(int c)
|
|
4053 {
|
|
4054 if (isdigit(c))
|
|
4055 return c - '0';
|
|
4056 c = TOLOWER_ASC(c);
|
|
4057 if (c >= 'a' && c <= 'f')
|
|
4058 return c - 'a' + 10;
|
|
4059 return -1000;
|
|
4060 }
|
|
4061
|
|
4062 /*
|
|
4063 * This function has been lifted from gui_w32.c and extended a bit.
|
|
4064 *
|
|
4065 * Return the Pixel value (color) for the given color name.
|
|
4066 * Return INVALCOLOR for error.
|
|
4067 */
|
|
4068 guicolor_T
|
|
4069 gui_mch_get_color(
|
|
4070 char_u *name)
|
|
4071 {
|
|
4072 typedef struct GuiColourTable
|
|
4073 {
|
|
4074 const char *name;
|
|
4075 guicolor_T colour;
|
|
4076 } GuiColourTable;
|
|
4077
|
|
4078 #define NSTATIC_COLOURS 50 // 32
|
|
4079 #define NDYNAMIC_COLOURS 33
|
|
4080 #define NCOLOURS (NSTATIC_COLOURS + NDYNAMIC_COLOURS)
|
|
4081
|
|
4082 static GuiColourTable table[NCOLOURS] =
|
|
4083 {
|
|
4084 {"Black", RGB(0x00, 0x00, 0x00)},
|
|
4085 {"DarkGray", RGB(0x80, 0x80, 0x80)},
|
|
4086 {"DarkGrey", RGB(0x80, 0x80, 0x80)},
|
|
4087 {"Gray", RGB(0xC0, 0xC0, 0xC0)},
|
|
4088 {"Grey", RGB(0xC0, 0xC0, 0xC0)},
|
|
4089 {"LightGray", RGB(0xD3, 0xD3, 0xD3)},
|
|
4090 {"LightGrey", RGB(0xD3, 0xD3, 0xD3)},
|
|
4091 {"Gray10", RGB(0x1A, 0x1A, 0x1A)},
|
|
4092 {"Grey10", RGB(0x1A, 0x1A, 0x1A)},
|
|
4093 {"Gray20", RGB(0x33, 0x33, 0x33)},
|
|
4094 {"Grey20", RGB(0x33, 0x33, 0x33)},
|
|
4095 {"Gray30", RGB(0x4D, 0x4D, 0x4D)},
|
|
4096 {"Grey30", RGB(0x4D, 0x4D, 0x4D)},
|
|
4097 {"Gray40", RGB(0x66, 0x66, 0x66)},
|
|
4098 {"Grey40", RGB(0x66, 0x66, 0x66)},
|
|
4099 {"Gray50", RGB(0x7F, 0x7F, 0x7F)},
|
|
4100 {"Grey50", RGB(0x7F, 0x7F, 0x7F)},
|
|
4101 {"Gray60", RGB(0x99, 0x99, 0x99)},
|
|
4102 {"Grey60", RGB(0x99, 0x99, 0x99)},
|
|
4103 {"Gray70", RGB(0xB3, 0xB3, 0xB3)},
|
|
4104 {"Grey70", RGB(0xB3, 0xB3, 0xB3)},
|
|
4105 {"Gray80", RGB(0xCC, 0xCC, 0xCC)},
|
|
4106 {"Grey80", RGB(0xCC, 0xCC, 0xCC)},
|
|
4107 {"Gray90", RGB(0xE5, 0xE5, 0xE5)},
|
|
4108 {"Grey90", RGB(0xE5, 0xE5, 0xE5)},
|
|
4109 {"White", RGB(0xFF, 0xFF, 0xFF)},
|
|
4110 {"DarkRed", RGB(0x80, 0x00, 0x00)},
|
|
4111 {"Red", RGB(0xFF, 0x00, 0x00)},
|
|
4112 {"LightRed", RGB(0xFF, 0xA0, 0xA0)},
|
|
4113 {"DarkBlue", RGB(0x00, 0x00, 0x80)},
|
|
4114 {"Blue", RGB(0x00, 0x00, 0xFF)},
|
|
4115 {"LightBlue", RGB(0xA0, 0xA0, 0xFF)},
|
|
4116 {"DarkGreen", RGB(0x00, 0x80, 0x00)},
|
|
4117 {"Green", RGB(0x00, 0xFF, 0x00)},
|
|
4118 {"LightGreen", RGB(0xA0, 0xFF, 0xA0)},
|
|
4119 {"DarkCyan", RGB(0x00, 0x80, 0x80)},
|
|
4120 {"Cyan", RGB(0x00, 0xFF, 0xFF)},
|
|
4121 {"LightCyan", RGB(0xA0, 0xFF, 0xFF)},
|
|
4122 {"DarkMagenta", RGB(0x80, 0x00, 0x80)},
|
|
4123 {"Magenta", RGB(0xFF, 0x00, 0xFF)},
|
|
4124 {"LightMagenta", RGB(0xFF, 0xA0, 0xFF)},
|
|
4125 {"Brown", RGB(0x80, 0x40, 0x40)},
|
|
4126 {"Yellow", RGB(0xFF, 0xFF, 0x00)},
|
|
4127 {"LightYellow", RGB(0xFF, 0xFF, 0xA0)},
|
|
4128 {"DarkYellow", RGB(0xBB, 0xBB, 0x00)},
|
|
4129 {"SeaGreen", RGB(0x2E, 0x8B, 0x57)},
|
|
4130 {"Orange", RGB(0xFF, 0xA5, 0x00)},
|
|
4131 {"Purple", RGB(0xA0, 0x20, 0xF0)},
|
|
4132 {"SlateBlue", RGB(0x6A, 0x5A, 0xCD)},
|
|
4133 {"Violet", RGB(0xEE, 0x82, 0xEE)},
|
|
4134 // NOTE: some entries are zero-allocated for NDDYNAMIC_COLORS
|
|
4135 // in this table!
|
|
4136 };
|
|
4137
|
|
4138 static int endColour = NSTATIC_COLOURS;
|
|
4139 static int newColour = NSTATIC_COLOURS;
|
|
4140
|
|
4141 int r, g, b;
|
|
4142 int i;
|
|
4143
|
|
4144 if (name[0] == '#' && STRLEN(name) == 7)
|
|
4145 {
|
|
4146 // Name is in "#rrggbb" format
|
|
4147 r = hex_digit(name[1]) * 16 + hex_digit(name[2]);
|
|
4148 g = hex_digit(name[3]) * 16 + hex_digit(name[4]);
|
|
4149 b = hex_digit(name[5]) * 16 + hex_digit(name[6]);
|
|
4150 if (r < 0 || g < 0 || b < 0)
|
|
4151 return INVALCOLOR;
|
|
4152 return RGB(r, g, b);
|
|
4153 }
|
|
4154 else
|
|
4155 {
|
|
4156 // Check if the name is one of the colours we know
|
|
4157 for (i = 0; i < endColour; i++)
|
|
4158 if (STRICMP(name, table[i].name) == 0)
|
|
4159 return table[i].colour;
|
|
4160 }
|
|
4161
|
|
4162 /*
|
|
4163 * Last attempt. Look in the file "$VIMRUNTIME/rgb.txt".
|
|
4164 */
|
|
4165 {
|
|
4166 #define LINE_LEN 100
|
|
4167 FILE *fd;
|
|
4168 char line[LINE_LEN];
|
|
4169 char_u *fname;
|
|
4170
|
|
4171 fname = expand_env_save((char_u *)"$VIMRUNTIME/rgb.txt");
|
|
4172 if (fname == NULL)
|
|
4173 return INVALCOLOR;
|
|
4174
|
|
4175 fd = fopen((char *)fname, "rt");
|
|
4176 vim_free(fname);
|
|
4177 if (fd == NULL)
|
|
4178 return INVALCOLOR;
|
|
4179
|
|
4180 while (!feof(fd))
|
|
4181 {
|
|
4182 int len;
|
|
4183 int pos;
|
|
4184 char *colour;
|
|
4185
|
|
4186 fgets(line, LINE_LEN, fd);
|
|
4187 len = strlen(line);
|
|
4188
|
|
4189 if (len <= 1 || line[len-1] != '\n')
|
|
4190 continue;
|
|
4191
|
|
4192 line[len-1] = '\0';
|
|
4193
|
|
4194 i = sscanf(line, "%d %d %d %n", &r, &g, &b, &pos);
|
|
4195 if (i != 3)
|
|
4196 continue;
|
|
4197
|
|
4198 colour = line + pos;
|
|
4199
|
|
4200 if (STRICMP(colour, name) == 0)
|
|
4201 {
|
|
4202 fclose(fd);
|
|
4203 /*
|
|
4204 * Now remember this colour in the table.
|
|
4205 * A LRU scheme might be better but this is simpler.
|
|
4206 * Or could use a growing array.
|
|
4207 */
|
|
4208 guicolor_T gcolour = RGB(r,g,b);
|
|
4209
|
|
4210 // NOTE: see note above in table allocation! We are working here with
|
|
4211 // dynamically allocated names, not constant ones!
|
|
4212 vim_free((char*)table[newColour].name);
|
|
4213 table[newColour].name = (char *)vim_strsave((char_u *)colour);
|
|
4214 table[newColour].colour = gcolour;
|
|
4215
|
|
4216 newColour++;
|
|
4217 if (newColour >= NCOLOURS)
|
|
4218 newColour = NSTATIC_COLOURS;
|
|
4219 if (endColour < NCOLOURS)
|
|
4220 endColour = newColour;
|
|
4221
|
|
4222 return gcolour;
|
|
4223 }
|
|
4224 }
|
|
4225
|
|
4226 fclose(fd);
|
|
4227 }
|
|
4228
|
|
4229 return INVALCOLOR;
|
|
4230 }
|
|
4231
|
|
4232 /*
|
|
4233 * Set the current text foreground color.
|
|
4234 */
|
|
4235 void
|
|
4236 gui_mch_set_fg_color(
|
|
4237 guicolor_T color)
|
|
4238 {
|
|
4239 rgb_color rgb = GUI_TO_RGB(color);
|
|
4240 if (gui.vimWindow->Lock()) {
|
|
4241 gui.vimTextArea->SetHighColor(rgb);
|
|
4242 gui.vimWindow->Unlock();
|
|
4243 }
|
|
4244 }
|
|
4245
|
|
4246 /*
|
|
4247 * Set the current text background color.
|
|
4248 */
|
|
4249 void
|
|
4250 gui_mch_set_bg_color(
|
|
4251 guicolor_T color)
|
|
4252 {
|
|
4253 rgb_color rgb = GUI_TO_RGB(color);
|
|
4254 if (gui.vimWindow->Lock()) {
|
|
4255 gui.vimTextArea->SetLowColor(rgb);
|
|
4256 gui.vimWindow->Unlock();
|
|
4257 }
|
|
4258 }
|
|
4259
|
|
4260 /*
|
|
4261 * Set the current text special color.
|
|
4262 */
|
|
4263 void
|
|
4264 gui_mch_set_sp_color(guicolor_T color)
|
|
4265 {
|
|
4266 // prev_sp_color = color;
|
|
4267 }
|
|
4268
|
|
4269 void
|
|
4270 gui_mch_draw_string(
|
|
4271 int row,
|
|
4272 int col,
|
|
4273 char_u *s,
|
|
4274 int len,
|
|
4275 int flags)
|
|
4276 {
|
|
4277 if (gui.vimWindow->Lock()) {
|
|
4278 gui.vimTextArea->mchDrawString(row, col, s, len, flags);
|
|
4279 gui.vimWindow->Unlock();
|
|
4280 }
|
|
4281 }
|
|
4282
|
|
4283 guicolor_T
|
|
4284 gui_mch_get_rgb_color(int r, int g, int b)
|
|
4285 {
|
|
4286 return gui_get_rgb_color_cmn(r, g, b);
|
|
4287 }
|
|
4288
|
|
4289
|
|
4290 // Return OK if the key with the termcap name "name" is supported.
|
|
4291 int
|
|
4292 gui_mch_haskey(
|
|
4293 char_u *name)
|
|
4294 {
|
|
4295 int i;
|
|
4296
|
|
4297 for (i = 0; special_keys[i].BeKeys != 0; i++)
|
|
4298 if (name[0] == special_keys[i].vim_code0 &&
|
|
4299 name[1] == special_keys[i].vim_code1)
|
|
4300 return OK;
|
|
4301 return FAIL;
|
|
4302 }
|
|
4303
|
|
4304 void
|
|
4305 gui_mch_beep()
|
|
4306 {
|
|
4307 ::beep();
|
|
4308 }
|
|
4309
|
|
4310 void
|
|
4311 gui_mch_flash(int msec)
|
|
4312 {
|
|
4313 // Do a visual beep by reversing the foreground and background colors
|
|
4314
|
|
4315 if (gui.vimWindow->Lock()) {
|
|
4316 BRect rect = gui.vimTextArea->Bounds();
|
|
4317
|
|
4318 gui.vimTextArea->SetDrawingMode(B_OP_INVERT);
|
|
4319 gui.vimTextArea->FillRect(rect);
|
|
4320 gui.vimTextArea->Sync();
|
|
4321 snooze(msec * 1000); // wait for a few msec
|
|
4322 gui.vimTextArea->FillRect(rect);
|
|
4323 gui.vimTextArea->SetDrawingMode(B_OP_COPY);
|
|
4324 gui.vimTextArea->Flush();
|
|
4325 gui.vimWindow->Unlock();
|
|
4326 }
|
|
4327 }
|
|
4328
|
|
4329 /*
|
|
4330 * Invert a rectangle from row r, column c, for nr rows and nc columns.
|
|
4331 */
|
|
4332 void
|
|
4333 gui_mch_invert_rectangle(
|
|
4334 int r,
|
|
4335 int c,
|
|
4336 int nr,
|
|
4337 int nc)
|
|
4338 {
|
|
4339 BRect rect;
|
|
4340 rect.left = FILL_X(c);
|
|
4341 rect.top = FILL_Y(r);
|
|
4342 rect.right = rect.left + nc * gui.char_width - PEN_WIDTH;
|
|
4343 rect.bottom = rect.top + nr * gui.char_height - PEN_WIDTH;
|
|
4344
|
|
4345 if (gui.vimWindow->Lock()) {
|
|
4346 gui.vimTextArea->SetDrawingMode(B_OP_INVERT);
|
|
4347 gui.vimTextArea->FillRect(rect);
|
|
4348 gui.vimTextArea->SetDrawingMode(B_OP_COPY);
|
|
4349 gui.vimWindow->Unlock();
|
|
4350 }
|
|
4351 }
|
|
4352
|
|
4353 /*
|
|
4354 * Iconify the GUI window.
|
|
4355 */
|
|
4356 void
|
|
4357 gui_mch_iconify()
|
|
4358 {
|
|
4359 if (gui.vimWindow->Lock()) {
|
|
4360 gui.vimWindow->Minimize(true);
|
|
4361 gui.vimWindow->Unlock();
|
|
4362 }
|
|
4363 }
|
|
4364
|
|
4365 #if defined(FEAT_EVAL) || defined(PROTO)
|
|
4366 /*
|
|
4367 * Bring the Vim window to the foreground.
|
|
4368 */
|
|
4369 void
|
|
4370 gui_mch_set_foreground(void)
|
|
4371 {
|
|
4372 // TODO
|
|
4373 }
|
|
4374 #endif
|
|
4375
|
|
4376 /*
|
|
4377 * Set the window title
|
|
4378 */
|
|
4379 void
|
|
4380 gui_mch_settitle(
|
|
4381 char_u *title,
|
|
4382 char_u *icon)
|
|
4383 {
|
|
4384 if (gui.vimWindow->Lock()) {
|
|
4385 gui.vimWindow->SetTitle((char *)title);
|
|
4386 gui.vimWindow->Unlock();
|
|
4387 }
|
|
4388 }
|
|
4389
|
|
4390 /*
|
|
4391 * Draw a cursor without focus.
|
|
4392 */
|
|
4393 void
|
|
4394 gui_mch_draw_hollow_cursor(guicolor_T color)
|
|
4395 {
|
|
4396 gui_mch_set_fg_color(color);
|
|
4397
|
|
4398 BRect r;
|
|
4399 r.left = FILL_X(gui.col);
|
|
4400 r.top = FILL_Y(gui.row);
|
|
4401 int cells = utf_off2cells(LineOffset[gui.row] + gui.col, 100); // TODO-TODO
|
|
4402 if(cells>=4) cells = 1;
|
|
4403 r.right = r.left + cells*gui.char_width - PEN_WIDTH;
|
|
4404 r.bottom = r.top + gui.char_height - PEN_WIDTH;
|
|
4405
|
|
4406 if (gui.vimWindow->Lock()) {
|
|
4407 gui.vimTextArea->StrokeRect(r);
|
|
4408 gui.vimWindow->Unlock();
|
|
4409 // gui_mch_flush();
|
|
4410 }
|
|
4411 }
|
|
4412
|
|
4413 /*
|
|
4414 * Draw part of a cursor, only w pixels wide, and h pixels high.
|
|
4415 */
|
|
4416 void
|
|
4417 gui_mch_draw_part_cursor(
|
|
4418 int w,
|
|
4419 int h,
|
|
4420 guicolor_T color)
|
|
4421 {
|
|
4422 gui_mch_set_fg_color(color);
|
|
4423
|
|
4424 BRect r;
|
|
4425 r.left =
|
|
4426 #ifdef FEAT_RIGHTLEFT
|
|
4427 // vertical line should be on the right of current point
|
|
4428 CURSOR_BAR_RIGHT ? FILL_X(gui.col + 1) - w :
|
|
4429 #endif
|
|
4430 FILL_X(gui.col);
|
|
4431 r.right = r.left + w - PEN_WIDTH;
|
|
4432 r.bottom = FILL_Y(gui.row + 1) - PEN_WIDTH;
|
|
4433 r.top = r.bottom - h + PEN_WIDTH;
|
|
4434
|
|
4435 if (gui.vimWindow->Lock()) {
|
|
4436 gui.vimTextArea->FillRect(r);
|
|
4437 gui.vimWindow->Unlock();
|
|
4438 // gui_mch_flush();
|
|
4439 }
|
|
4440 }
|
|
4441
|
|
4442 /*
|
|
4443 * Catch up with any queued events. This may put keyboard input into the
|
|
4444 * input buffer, call resize call-backs, trigger timers etc. If there is
|
|
4445 * nothing in the event queue (& no timers pending), then we return
|
|
4446 * immediately.
|
|
4447 */
|
|
4448 void
|
|
4449 gui_mch_update()
|
|
4450 {
|
|
4451 gui_mch_flush();
|
|
4452 while (port_count(gui.vdcmp) > 0 &&
|
|
4453 !vim_is_input_buf_full() &&
|
|
4454 gui_haiku_process_event(0) >= B_OK)
|
|
4455 /* nothing */ ;
|
|
4456 }
|
|
4457
|
|
4458 /*
|
|
4459 * GUI input routine called by gui_wait_for_chars(). Waits for a character
|
|
4460 * from the keyboard.
|
|
4461 * wtime == -1 Wait forever.
|
|
4462 * wtime == 0 This should never happen.
|
|
4463 * wtime > 0 Wait wtime milliseconds for a character.
|
|
4464 * Returns OK if a character was found to be available within the given time,
|
|
4465 * or FAIL otherwise.
|
|
4466 */
|
|
4467 int
|
|
4468 gui_mch_wait_for_chars(
|
|
4469 int wtime)
|
|
4470 {
|
|
4471 int focus;
|
|
4472 bigtime_t until, timeout;
|
|
4473 status_t st;
|
|
4474
|
|
4475 if (wtime >= 0) {
|
|
4476 timeout = wtime * 1000;
|
|
4477 until = system_time() + timeout;
|
|
4478 } else {
|
|
4479 timeout = B_INFINITE_TIMEOUT;
|
|
4480 }
|
|
4481
|
|
4482 focus = gui.in_focus;
|
|
4483 for (;;)
|
|
4484 {
|
|
4485 // Stop or start blinking when focus changes
|
|
4486 if (gui.in_focus != focus)
|
|
4487 {
|
|
4488 if (gui.in_focus)
|
|
4489 gui_mch_start_blink();
|
|
4490 else
|
|
4491 gui_mch_stop_blink();
|
|
4492 focus = gui.in_focus;
|
|
4493 }
|
|
4494
|
|
4495 gui_mch_flush();
|
|
4496 /*
|
|
4497 * Don't use gui_mch_update() because then we will spin-lock until a
|
|
4498 * char arrives, instead we use gui_haiku_process_event() to hang until
|
|
4499 * an event arrives. No need to check for input_buf_full because we
|
|
4500 * are returning as soon as it contains a single char.
|
|
4501 */
|
|
4502 st = gui_haiku_process_event(timeout);
|
|
4503
|
|
4504 if (input_available())
|
|
4505 return OK;
|
|
4506 if (st < B_OK) // includes B_TIMED_OUT
|
|
4507 return FAIL;
|
|
4508
|
|
4509 /*
|
|
4510 * Calculate how much longer we're willing to wait for the
|
|
4511 * next event.
|
|
4512 */
|
|
4513 if (wtime >= 0) {
|
|
4514 timeout = until - system_time();
|
|
4515 if (timeout < 0)
|
|
4516 break;
|
|
4517 }
|
|
4518 }
|
|
4519 return FAIL;
|
|
4520
|
|
4521 }
|
|
4522
|
|
4523 /*
|
|
4524 * Output routines.
|
|
4525 */
|
|
4526
|
|
4527 /*
|
|
4528 * Flush any output to the screen. This is typically called before
|
|
4529 * the app goes to sleep.
|
|
4530 */
|
|
4531 void
|
|
4532 gui_mch_flush()
|
|
4533 {
|
|
4534 // does this need to lock the window? Apparently not but be safe.
|
|
4535 if (gui.vimWindow->Lock()) {
|
|
4536 gui.vimWindow->Flush();
|
|
4537 gui.vimWindow->Unlock();
|
|
4538 }
|
|
4539 return;
|
|
4540 }
|
|
4541
|
|
4542 /*
|
|
4543 * Clear a rectangular region of the screen from text pos (row1, col1) to
|
|
4544 * (row2, col2) inclusive.
|
|
4545 */
|
|
4546 void
|
|
4547 gui_mch_clear_block(
|
|
4548 int row1,
|
|
4549 int col1,
|
|
4550 int row2,
|
|
4551 int col2)
|
|
4552 {
|
|
4553 if (gui.vimWindow->Lock()) {
|
|
4554 gui.vimTextArea->mchClearBlock(row1, col1, row2, col2);
|
|
4555 gui.vimWindow->Unlock();
|
|
4556 }
|
|
4557 }
|
|
4558
|
|
4559 void
|
|
4560 gui_mch_clear_all()
|
|
4561 {
|
|
4562 if (gui.vimWindow->Lock()) {
|
|
4563 gui.vimTextArea->mchClearAll();
|
|
4564 gui.vimWindow->Unlock();
|
|
4565 }
|
|
4566 }
|
|
4567
|
|
4568 /*
|
|
4569 * Delete the given number of lines from the given row, scrolling up any
|
|
4570 * text further down within the scroll region.
|
|
4571 */
|
|
4572 void
|
|
4573 gui_mch_delete_lines(
|
|
4574 int row,
|
|
4575 int num_lines)
|
|
4576 {
|
|
4577 gui.vimTextArea->mchDeleteLines(row, num_lines);
|
|
4578 }
|
|
4579
|
|
4580 /*
|
|
4581 * Insert the given number of lines before the given row, scrolling down any
|
|
4582 * following text within the scroll region.
|
|
4583 */
|
|
4584 void
|
|
4585 gui_mch_insert_lines(
|
|
4586 int row,
|
|
4587 int num_lines)
|
|
4588 {
|
|
4589 gui.vimTextArea->mchInsertLines(row, num_lines);
|
|
4590 }
|
|
4591
|
|
4592 #if defined(FEAT_MENU) || defined(PROTO)
|
|
4593 /*
|
|
4594 * Menu stuff.
|
|
4595 */
|
|
4596
|
|
4597 void
|
|
4598 gui_mch_enable_menu(
|
|
4599 int flag)
|
|
4600 {
|
|
4601 if (gui.vimWindow->Lock())
|
|
4602 {
|
|
4603 BMenuBar *menubar = gui.vimForm->MenuBar();
|
|
4604 menubar->SetEnabled(flag);
|
|
4605 gui.vimWindow->Unlock();
|
|
4606 }
|
|
4607 }
|
|
4608
|
|
4609 void
|
|
4610 gui_mch_set_menu_pos(
|
|
4611 int x,
|
|
4612 int y,
|
|
4613 int w,
|
|
4614 int h)
|
|
4615 {
|
|
4616 // It will be in the right place anyway
|
|
4617 }
|
|
4618
|
|
4619 /*
|
|
4620 * Add a sub menu to the menu bar.
|
|
4621 */
|
|
4622 void
|
|
4623 gui_mch_add_menu(
|
|
4624 vimmenu_T *menu,
|
|
4625 int idx)
|
|
4626 {
|
|
4627 vimmenu_T *parent = menu->parent;
|
|
4628
|
|
4629 // popup menu - just create it unattached
|
|
4630 if (menu_is_popup(menu->name) && parent == NULL) {
|
|
4631 BPopUpMenu* popUpMenu = new BPopUpMenu((const char*)menu->name, false, false);
|
|
4632 menu->submenu_id = popUpMenu;
|
|
4633 menu->id = NULL;
|
|
4634 return;
|
|
4635 }
|
|
4636
|
|
4637 if (!menu_is_menubar(menu->name)
|
|
4638 || (parent != NULL && parent->submenu_id == NULL))
|
|
4639 return;
|
|
4640
|
|
4641 if (gui.vimWindow->Lock())
|
|
4642 {
|
|
4643 // Major re-write of the menu code, it was failing with memory corruption when
|
|
4644 // we started loading multiple files (the Buffer menu)
|
|
4645 //
|
|
4646 // Note we don't use the preference values yet, all are inserted into the
|
|
4647 // menubar on a first come-first served basis...
|
|
4648 //
|
|
4649 // richard@whitequeen.com jul 99
|
|
4650
|
|
4651 BMenu *tmp;
|
|
4652
|
|
4653 if ( parent )
|
|
4654 tmp = parent->submenu_id;
|
|
4655 else
|
|
4656 tmp = gui.vimForm->MenuBar();
|
|
4657 // make sure we don't try and add the same menu twice. The Buffers menu tries to
|
|
4658 // do this and Be starts to crash...
|
|
4659
|
|
4660 if ( ! tmp->FindItem((const char *) menu->dname)) {
|
|
4661
|
|
4662 BMenu *bmenu = new BMenu((char *)menu->dname);
|
|
4663
|
|
4664 menu->submenu_id = bmenu;
|
|
4665
|
|
4666 // when we add a BMenu to another Menu, it creates the interconnecting BMenuItem
|
|
4667 tmp->AddItem(bmenu);
|
|
4668
|
|
4669 // Now its safe to query the menu for the associated MenuItem....
|
|
4670 menu->id = tmp->FindItem((const char *) menu->dname);
|
|
4671
|
|
4672 }
|
|
4673 gui.vimWindow->Unlock();
|
|
4674 }
|
|
4675 }
|
|
4676
|
|
4677 void
|
|
4678 gui_mch_toggle_tearoffs(int enable)
|
|
4679 {
|
|
4680 // no tearoff menus
|
|
4681 }
|
|
4682
|
|
4683 static BMessage *
|
|
4684 MenuMessage(vimmenu_T *menu)
|
|
4685 {
|
|
4686 BMessage *m = new BMessage('menu');
|
|
4687 m->AddPointer("VimMenu", (void *)menu);
|
|
4688
|
|
4689 return m;
|
|
4690 }
|
|
4691
|
|
4692 /*
|
|
4693 * Add a menu item to a menu
|
|
4694 */
|
|
4695 void
|
|
4696 gui_mch_add_menu_item(
|
|
4697 vimmenu_T *menu,
|
|
4698 int idx)
|
|
4699 {
|
|
4700 int mnemonic = 0;
|
|
4701 vimmenu_T *parent = menu->parent;
|
|
4702
|
|
4703 // TODO: use menu->actext
|
|
4704 // This is difficult, since on Be, an accelerator must be a single char
|
|
4705 // and a lot of Vim ones are the standard VI commands.
|
|
4706 //
|
|
4707 // Punt for Now...
|
|
4708 // richard@whiequeen.com jul 99
|
|
4709 if (gui.vimWindow->Lock())
|
|
4710 {
|
|
4711 #ifdef FEAT_TOOLBAR
|
|
4712 if(menu_is_toolbar(parent->name)) {
|
|
4713 VimToolbar *toolbar = gui.vimForm->ToolBar();
|
|
4714 if(toolbar != NULL) {
|
|
4715 toolbar->AddButton(idx, menu);
|
|
4716 }
|
|
4717 } else
|
|
4718 #endif
|
|
4719
|
|
4720 if (parent->submenu_id != NULL || menu_is_popup(parent->name)) {
|
|
4721 if (menu_is_separator(menu->name)) {
|
|
4722 BSeparatorItem *item = new BSeparatorItem();
|
|
4723 parent->submenu_id->AddItem(item);
|
|
4724 menu->id = item;
|
|
4725 menu->submenu_id = NULL;
|
|
4726 }
|
|
4727 else {
|
|
4728 BMenuItem *item = new BMenuItem((char *)menu->dname,
|
|
4729 MenuMessage(menu));
|
|
4730 item->SetTarget(gui.vimTextArea);
|
|
4731 item->SetTrigger((char) menu->mnemonic);
|
|
4732 parent->submenu_id->AddItem(item);
|
|
4733 menu->id = item;
|
|
4734 menu->submenu_id = NULL;
|
|
4735 }
|
|
4736 }
|
|
4737 gui.vimWindow->Unlock();
|
|
4738 }
|
|
4739 }
|
|
4740
|
|
4741 /*
|
|
4742 * Destroy the machine specific menu widget.
|
|
4743 */
|
|
4744 void
|
|
4745 gui_mch_destroy_menu(
|
|
4746 vimmenu_T *menu)
|
|
4747 {
|
|
4748 if (gui.vimWindow->Lock())
|
|
4749 {
|
|
4750 #ifdef FEAT_TOOLBAR
|
|
4751 if(menu->parent && menu_is_toolbar(menu->parent->name)) {
|
|
4752 VimToolbar *toolbar = gui.vimForm->ToolBar();
|
|
4753 if(toolbar != NULL) {
|
|
4754 toolbar->RemoveButton(menu);
|
|
4755 }
|
|
4756 } else
|
|
4757 #endif
|
|
4758 {
|
|
4759 assert(menu->submenu_id == NULL || menu->submenu_id->CountItems() == 0);
|
|
4760 /*
|
|
4761 * Detach this menu from its parent, so that it is not deleted
|
|
4762 * twice once we get to delete that parent.
|
|
4763 * Deleting a BMenuItem also deletes the associated BMenu, if any
|
|
4764 * (which does not have any items anymore since they were
|
|
4765 * removed and deleted before).
|
|
4766 */
|
|
4767 BMenu *bmenu = menu->id->Menu();
|
|
4768 if (bmenu)
|
|
4769 {
|
|
4770 bmenu->RemoveItem(menu->id);
|
|
4771 /*
|
|
4772 * If we removed the last item from the menu bar,
|
|
4773 * resize it out of sight.
|
|
4774 */
|
|
4775 if (bmenu == gui.vimForm->MenuBar() && bmenu->CountItems() == 0)
|
|
4776 {
|
|
4777 bmenu->ResizeTo(-MENUBAR_MARGIN, -MENUBAR_MARGIN);
|
|
4778 }
|
|
4779 }
|
|
4780 delete menu->id;
|
|
4781 menu->id = NULL;
|
|
4782 menu->submenu_id = NULL;
|
|
4783
|
|
4784 gui.menu_height = (int) gui.vimForm->MenuHeight();
|
|
4785 }
|
|
4786 gui.vimWindow->Unlock();
|
|
4787 }
|
|
4788 }
|
|
4789
|
|
4790 /*
|
|
4791 * Make a menu either grey or not grey.
|
|
4792 */
|
|
4793 void
|
|
4794 gui_mch_menu_grey(
|
|
4795 vimmenu_T *menu,
|
|
4796 int grey)
|
|
4797 {
|
|
4798 #ifdef FEAT_TOOLBAR
|
|
4799 if(menu->parent && menu_is_toolbar(menu->parent->name)) {
|
|
4800 if (gui.vimWindow->Lock()) {
|
|
4801 VimToolbar *toolbar = gui.vimForm->ToolBar();
|
|
4802 if(toolbar != NULL) {
|
|
4803 toolbar->GrayButton(menu, grey);
|
|
4804 }
|
|
4805 gui.vimWindow->Unlock();
|
|
4806 }
|
|
4807 } else
|
|
4808 #endif
|
|
4809 if (menu->id != NULL)
|
|
4810 menu->id->SetEnabled(!grey);
|
|
4811 }
|
|
4812
|
|
4813 /*
|
|
4814 * Make menu item hidden or not hidden
|
|
4815 */
|
|
4816 void
|
|
4817 gui_mch_menu_hidden(
|
|
4818 vimmenu_T *menu,
|
|
4819 int hidden)
|
|
4820 {
|
|
4821 if (menu->id != NULL)
|
|
4822 menu->id->SetEnabled(!hidden);
|
|
4823 }
|
|
4824
|
|
4825 /*
|
|
4826 * This is called after setting all the menus to grey/hidden or not.
|
|
4827 */
|
|
4828 void
|
|
4829 gui_mch_draw_menubar()
|
|
4830 {
|
|
4831 // Nothing to do in BeOS
|
|
4832 }
|
|
4833
|
|
4834 void
|
|
4835 gui_mch_show_popupmenu(vimmenu_T *menu)
|
|
4836 {
|
|
4837 if (!menu_is_popup(menu->name) || menu->submenu_id == NULL)
|
|
4838 return;
|
|
4839
|
|
4840 BPopUpMenu* popupMenu = dynamic_cast<BPopUpMenu*>(menu->submenu_id);
|
|
4841 if (popupMenu == NULL)
|
|
4842 return;
|
|
4843
|
|
4844 BPoint point;
|
|
4845 if(gui.vimWindow->Lock()) {
|
|
4846 uint32 buttons = 0;
|
|
4847 gui.vimTextArea->GetMouse(&point, &buttons);
|
|
4848 gui.vimTextArea->ConvertToScreen(&point);
|
|
4849 gui.vimWindow->Unlock();
|
|
4850 }
|
|
4851 popupMenu->Go(point, true);
|
|
4852 }
|
|
4853
|
|
4854 #endif // FEAT_MENU
|
|
4855
|
|
4856 // Mouse stuff
|
|
4857
|
|
4858 #ifdef FEAT_CLIPBOARD
|
|
4859 /*
|
|
4860 * Clipboard stuff, for cutting and pasting text to other windows.
|
|
4861 */
|
|
4862 char textplain[] = "text/plain";
|
|
4863 char vimselectiontype[] = "application/x-vnd.Rhialto-Vim-selectiontype";
|
|
4864
|
|
4865 /*
|
|
4866 * Get the current selection and put it in the clipboard register.
|
|
4867 */
|
|
4868 void
|
|
4869 clip_mch_request_selection(Clipboard_T *cbd)
|
|
4870 {
|
|
4871 if (be_clipboard->Lock())
|
|
4872 {
|
|
4873 BMessage *m = be_clipboard->Data();
|
|
4874 // m->PrintToStream();
|
|
4875
|
|
4876 char_u *string = NULL;
|
|
4877 ssize_t stringlen = -1;
|
|
4878
|
|
4879 if (m->FindData(textplain, B_MIME_TYPE,
|
|
4880 (const void **)&string, &stringlen) == B_OK
|
|
4881 || m->FindString("text", (const char **)&string) == B_OK)
|
|
4882 {
|
|
4883 if (stringlen == -1)
|
|
4884 stringlen = STRLEN(string);
|
|
4885
|
|
4886 int type;
|
|
4887 char *seltype;
|
|
4888 ssize_t seltypelen;
|
|
4889
|
|
4890 /*
|
|
4891 * Try to get the special vim selection type first
|
|
4892 */
|
|
4893 if (m->FindData(vimselectiontype, B_MIME_TYPE,
|
|
4894 (const void **)&seltype, &seltypelen) == B_OK)
|
|
4895 {
|
|
4896 switch (*seltype)
|
|
4897 {
|
|
4898 default:
|
|
4899 case 'L': type = MLINE; break;
|
|
4900 case 'C': type = MCHAR; break;
|
|
4901 #ifdef FEAT_VISUAL
|
|
4902 case 'B': type = MBLOCK; break;
|
|
4903 #endif
|
|
4904 }
|
|
4905 }
|
|
4906 else
|
|
4907 {
|
|
4908 // Otherwise use heuristic as documented
|
|
4909 type = memchr(string, stringlen, '\n') ? MLINE : MCHAR;
|
|
4910 }
|
|
4911 clip_yank_selection(type, string, (long)stringlen, cbd);
|
|
4912 }
|
|
4913 be_clipboard->Unlock();
|
|
4914 }
|
|
4915 }
|
|
4916 /*
|
|
4917 * Make vim the owner of the current selection.
|
|
4918 */
|
|
4919 void
|
|
4920 clip_mch_lose_selection(Clipboard_T *cbd)
|
|
4921 {
|
|
4922 // Nothing needs to be done here
|
|
4923 }
|
|
4924
|
|
4925 /*
|
|
4926 * Make vim the owner of the current selection. Return OK upon success.
|
|
4927 */
|
|
4928 int
|
|
4929 clip_mch_own_selection(Clipboard_T *cbd)
|
|
4930 {
|
|
4931 /*
|
|
4932 * Never actually own the clipboard. If another application sets the
|
|
4933 * clipboard, we don't want to think that we still own it.
|
|
4934 */
|
|
4935 return FAIL;
|
|
4936 }
|
|
4937
|
|
4938 /*
|
|
4939 * Send the current selection to the clipboard.
|
|
4940 */
|
|
4941 void
|
|
4942 clip_mch_set_selection(Clipboard_T *cbd)
|
|
4943 {
|
|
4944 if (be_clipboard->Lock())
|
|
4945 {
|
|
4946 be_clipboard->Clear();
|
|
4947 BMessage *m = be_clipboard->Data();
|
|
4948 assert(m);
|
|
4949
|
|
4950 // If the '*' register isn't already filled in, fill it in now
|
|
4951 cbd->owned = TRUE;
|
|
4952 clip_get_selection(cbd);
|
|
4953 cbd->owned = FALSE;
|
|
4954
|
|
4955 char_u *str = NULL;
|
|
4956 long_u count;
|
|
4957 int type;
|
|
4958
|
|
4959 type = clip_convert_selection(&str, &count, cbd);
|
|
4960
|
|
4961 if (type < 0)
|
|
4962 return;
|
|
4963
|
|
4964 m->AddData(textplain, B_MIME_TYPE, (void *)str, count);
|
|
4965
|
|
4966 // Add type of selection
|
|
4967 char vtype;
|
|
4968 switch (type)
|
|
4969 {
|
|
4970 default:
|
|
4971 case MLINE: vtype = 'L'; break;
|
|
4972 case MCHAR: vtype = 'C'; break;
|
|
4973 #ifdef FEAT_VISUAL
|
|
4974 case MBLOCK: vtype = 'B'; break;
|
|
4975 #endif
|
|
4976 }
|
|
4977 m->AddData(vimselectiontype, B_MIME_TYPE, (void *)&vtype, 1);
|
|
4978
|
|
4979 vim_free(str);
|
|
4980
|
|
4981 be_clipboard->Commit();
|
|
4982 be_clipboard->Unlock();
|
|
4983 }
|
|
4984 }
|
|
4985
|
|
4986 #endif // FEAT_CLIPBOARD
|
|
4987
|
|
4988 #ifdef FEAT_BROWSE
|
|
4989 /*
|
|
4990 * Pop open a file browser and return the file selected, in allocated memory,
|
|
4991 * or NULL if Cancel is hit.
|
|
4992 * saving - TRUE if the file will be saved to, FALSE if it will be opened.
|
|
4993 * title - Title message for the file browser dialog.
|
|
4994 * dflt - Default name of file.
|
|
4995 * ext - Default extension to be added to files without extensions.
|
|
4996 * initdir - directory in which to open the browser (NULL = current dir)
|
|
4997 * filter - Filter for matched files to choose from.
|
|
4998 * Has a format like this:
|
|
4999 * "C Files (*.c)\0*.c\0"
|
|
5000 * "All Files\0*.*\0\0"
|
|
5001 * If these two strings were concatenated, then a choice of two file
|
|
5002 * filters will be selectable to the user. Then only matching files will
|
|
5003 * be shown in the browser. If NULL, the default allows all files.
|
|
5004 *
|
|
5005 * *NOTE* - the filter string must be terminated with TWO nulls.
|
|
5006 */
|
|
5007 char_u *
|
|
5008 gui_mch_browse(
|
|
5009 int saving,
|
|
5010 char_u *title,
|
|
5011 char_u *dflt,
|
|
5012 char_u *ext,
|
|
5013 char_u *initdir,
|
|
5014 char_u *filter)
|
|
5015 {
|
|
5016 gui.vimApp->fFilePanel = new BFilePanel((saving == TRUE) ? B_SAVE_PANEL : B_OPEN_PANEL,
|
|
5017 NULL, NULL, 0, false,
|
|
5018 new BMessage((saving == TRUE) ? 'save' : 'open'), NULL, true);
|
|
5019
|
|
5020 gui.vimApp->fBrowsedPath.Unset();
|
|
5021
|
|
5022 gui.vimApp->fFilePanel->Window()->SetTitle((char*)title);
|
|
5023 gui.vimApp->fFilePanel->SetPanelDirectory((const char*)initdir);
|
|
5024
|
|
5025 gui.vimApp->fFilePanel->Show();
|
|
5026
|
|
5027 gui.vimApp->fFilePanelSem = create_sem(0, "FilePanelSem");
|
|
5028
|
|
5029 while(acquire_sem(gui.vimApp->fFilePanelSem) == B_INTERRUPTED);
|
|
5030
|
|
5031 char_u *fileName = NULL;
|
|
5032 status_t result = gui.vimApp->fBrowsedPath.InitCheck();
|
|
5033 if(result == B_OK) {
|
|
5034 fileName = vim_strsave((char_u*)gui.vimApp->fBrowsedPath.Path());
|
|
5035 } else
|
|
5036 if(result != B_NO_INIT) {
|
|
5037 fprintf(stderr, "gui_mch_browse: BPath error: %#08x (%s)\n",
|
|
5038 result, strerror(result));
|
|
5039 }
|
|
5040
|
|
5041 delete gui.vimApp->fFilePanel;
|
|
5042 gui.vimApp->fFilePanel = NULL;
|
|
5043
|
|
5044 return fileName;
|
|
5045 }
|
|
5046 #endif // FEAT_BROWSE
|
|
5047
|
|
5048
|
|
5049 #if defined(FEAT_GUI_DIALOG)
|
|
5050
|
|
5051 /*
|
|
5052 * Create a dialog dynamically from the parameter strings.
|
|
5053 * type = type of dialog (question, alert, etc.)
|
|
5054 * title = dialog title. may be NULL for default title.
|
|
5055 * message = text to display. Dialog sizes to accommodate it.
|
|
5056 * buttons = '\n' separated list of button captions, default first.
|
|
5057 * dfltbutton = number of default button.
|
|
5058 *
|
|
5059 * This routine returns 1 if the first button is pressed,
|
|
5060 * 2 for the second, etc.
|
|
5061 *
|
|
5062 * 0 indicates Esc was pressed.
|
|
5063 * -1 for unexpected error
|
|
5064 *
|
|
5065 * If stubbing out this fn, return 1.
|
|
5066 */
|
|
5067
|
|
5068 int
|
|
5069 gui_mch_dialog(
|
|
5070 int type,
|
|
5071 char_u *title,
|
|
5072 char_u *message,
|
|
5073 char_u *buttons,
|
|
5074 int dfltbutton,
|
|
5075 char_u *textfield,
|
|
5076 int ex_cmd)
|
|
5077 {
|
|
5078 VimDialog *dialog = new VimDialog(type, (char*)title, (char*)message,
|
|
5079 (char*)buttons, dfltbutton, (char*)textfield, ex_cmd);
|
|
5080 return dialog->Go();
|
|
5081 }
|
|
5082
|
|
5083 #endif // FEAT_GUI_DIALOG
|
|
5084
|
|
5085
|
|
5086 /*
|
|
5087 * Return the RGB value of a pixel as long.
|
|
5088 */
|
|
5089 guicolor_T
|
|
5090 gui_mch_get_rgb(guicolor_T pixel)
|
|
5091 {
|
|
5092 rgb_color rgb = GUI_TO_RGB(pixel);
|
|
5093
|
|
5094 return ((rgb.red & 0xff) << 16) + ((rgb.green & 0xff) << 8)
|
|
5095 + (rgb.blue & 0xff);
|
|
5096 }
|
|
5097
|
|
5098 void
|
|
5099 gui_mch_setmouse(int x, int y)
|
|
5100 {
|
|
5101 TRACE();
|
|
5102 // TODO
|
|
5103 }
|
|
5104
|
|
5105 #ifdef FEAT_MBYTE_IME
|
|
5106 void
|
|
5107 im_set_position(int row, int col)
|
|
5108 {
|
|
5109 if(gui.vimWindow->Lock())
|
|
5110 {
|
|
5111 gui.vimTextArea->DrawIMString();
|
|
5112 gui.vimWindow->Unlock();
|
|
5113 }
|
|
5114 return;
|
|
5115 }
|
|
5116 #endif
|
|
5117
|
|
5118 void
|
|
5119 gui_mch_show_toolbar(int showit)
|
|
5120 {
|
|
5121 VimToolbar *toolbar = gui.vimForm->ToolBar();
|
|
5122 gui.toolbar_height = (toolbar && showit) ? toolbar->ToolbarHeight() : 0.;
|
|
5123 }
|
|
5124
|
|
5125 void
|
|
5126 gui_mch_set_toolbar_pos(int x, int y, int w, int h)
|
|
5127 {
|
|
5128 VimToolbar *toolbar = gui.vimForm->ToolBar();
|
|
5129 if(toolbar != NULL) {
|
|
5130 if (gui.vimWindow->Lock()) {
|
|
5131 toolbar->MoveTo(x, y);
|
|
5132 toolbar->ResizeTo(w - 1, h - 1);
|
|
5133 gui.vimWindow->Unlock();
|
|
5134 }
|
|
5135 }
|
|
5136 }
|
|
5137
|
|
5138 #if defined(FEAT_GUI_TABLINE) || defined(PROTO)
|
|
5139
|
|
5140 /*
|
|
5141 * Show or hide the tabline.
|
|
5142 */
|
|
5143 void
|
|
5144 gui_mch_show_tabline(int showit)
|
|
5145 {
|
|
5146 VimTabLine *tabLine = gui.vimForm->TabLine();
|
|
5147
|
|
5148 if (tabLine == NULL)
|
|
5149 return;
|
|
5150
|
|
5151 if (!showit != !gui.vimForm->IsShowingTabLine()) {
|
|
5152 gui.vimForm->SetShowingTabLine(showit != 0);
|
|
5153 gui.tabline_height = gui.vimForm->TablineHeight();
|
|
5154 }
|
|
5155 }
|
|
5156
|
|
5157 void
|
|
5158 gui_mch_set_tabline_pos(int x, int y, int w, int h)
|
|
5159 {
|
|
5160 VimTabLine *tabLine = gui.vimForm->TabLine();
|
|
5161 if(tabLine != NULL) {
|
|
5162 if (gui.vimWindow->Lock()) {
|
|
5163 tabLine->MoveTo(x, y);
|
|
5164 tabLine->ResizeTo(w - 1, h - 1);
|
|
5165 gui.vimWindow->Unlock();
|
|
5166 }
|
|
5167 }
|
|
5168 }
|
|
5169
|
|
5170 /*
|
|
5171 * Return TRUE when tabline is displayed.
|
|
5172 */
|
|
5173 int
|
|
5174 gui_mch_showing_tabline()
|
|
5175 {
|
|
5176 VimTabLine *tabLine = gui.vimForm->TabLine();
|
|
5177 return tabLine != NULL && gui.vimForm->IsShowingTabLine();
|
|
5178 }
|
|
5179
|
|
5180 /*
|
|
5181 * Update the labels of the tabline.
|
|
5182 */
|
|
5183 void
|
|
5184 gui_mch_update_tabline()
|
|
5185 {
|
|
5186 tabpage_T *tp;
|
|
5187 int nr = 0;
|
|
5188 int curtabidx = 0;
|
|
5189
|
|
5190 VimTabLine *tabLine = gui.vimForm->TabLine();
|
|
5191
|
|
5192 if (tabLine == NULL)
|
|
5193 return;
|
|
5194
|
|
5195 gui.vimWindow->Lock();
|
|
5196
|
|
5197 // Add a label for each tab page. They all contain the same text area.
|
|
5198 for (tp = first_tabpage; tp != NULL; tp = tp->tp_next, ++nr) {
|
|
5199 if (tp == curtab)
|
|
5200 curtabidx = nr;
|
|
5201
|
|
5202 BTab* tab = tabLine->TabAt(nr);
|
|
5203
|
|
5204 if (tab == NULL) {
|
|
5205 tab = new VimTabLine::VimTab();
|
|
5206 tabLine->AddTab(NULL, tab);
|
|
5207 }
|
|
5208
|
|
5209 get_tabline_label(tp, FALSE);
|
|
5210 tab->SetLabel((const char*)NameBuff);
|
|
5211 tabLine->Invalidate();
|
|
5212 }
|
|
5213
|
|
5214 // Remove any old labels.
|
|
5215 while (nr < tabLine->CountTabs())
|
|
5216 tabLine->RemoveTab(nr);
|
|
5217
|
|
5218 if(tabLine->Selection() != curtabidx)
|
|
5219 tabLine->Select(curtabidx);
|
|
5220
|
|
5221 gui.vimWindow->Unlock();
|
|
5222 }
|
|
5223
|
|
5224 /*
|
|
5225 * Set the current tab to "nr". First tab is 1.
|
|
5226 */
|
|
5227 void
|
|
5228 gui_mch_set_curtab(int nr)
|
|
5229 {
|
|
5230 VimTabLine *tabLine = gui.vimForm->TabLine();
|
|
5231 if(tabLine == NULL)
|
|
5232 return;
|
|
5233
|
|
5234 gui.vimWindow->Lock();
|
|
5235
|
|
5236 if(tabLine->Selection() != nr -1)
|
|
5237 tabLine->Select(nr -1);
|
|
5238
|
|
5239 gui.vimWindow->Unlock();
|
|
5240 }
|
|
5241
|
|
5242 #endif // FEAT_GUI_TABLINE
|