Bram Moolenaar | edf3f97 | 2016-08-29 22:49:24 +0200 | [diff] [blame^] | 1 | /* vi:set ts=8 sts=4 sw=4 noet: |
Bram Moolenaar | 071d427 | 2004-06-13 20:20:40 +0000 | [diff] [blame] | 2 | * |
| 3 | * VIM - Vi IMproved by Bram Moolenaar |
| 4 | * Visual Workshop integration by Gordon Prieur |
| 5 | * |
| 6 | * Do ":help uganda" in Vim to read copying and usage conditions. |
| 7 | * Do ":help credits" in Vim to see a list of people who contributed. |
| 8 | */ |
| 9 | /* |
| 10 | THIS IS AN UNSTABLE INTERFACE! It is unsupported and will likely |
| 11 | change in future releases, possibly breaking compatibility! |
| 12 | */ |
| 13 | |
| 14 | #ifndef _INTEGRATION_H |
| 15 | #define _INTEGRATION_H |
| 16 | |
| 17 | #include <X11/Intrinsic.h> |
| 18 | #include <Xm/Xm.h> |
| 19 | |
| 20 | #ifdef __cplusplus |
| 21 | extern "C" { |
| 22 | #endif |
| 23 | |
| 24 | /* Enable NoHands test support functions. Define this only if you want to |
| 25 | compile in support in the editor such that it can be run under |
| 26 | the WorkShop test suite. */ |
| 27 | #ifndef NOHANDS_SUPPORT_FUNCTIONS |
| 28 | #define NOHANDS_SUPPORT_FUNCTIONS |
| 29 | #endif |
| 30 | |
| 31 | |
| 32 | /* This header file has three parts. |
| 33 | * 1. Functions you need to implement; these are called by the integration |
| 34 | * library |
| 35 | * 2. Functions you need to call when certain events happen in the editor; |
| 36 | * these are implemented by the integration library |
| 37 | * 3. Utility functions provided by the integration library; these make |
| 38 | * task 1 a bit easier. |
| 39 | */ |
| 40 | |
| 41 | /* |
| 42 | * The following functions need to be implemented by the editor |
| 43 | * integration code (and will be editor-specific). Please see the |
| 44 | * sample workshop.c file for comments explaining what each functions |
| 45 | * needs to do, what the arguments mean, etc. |
| 46 | */ |
| 47 | |
| 48 | /* |
| 49 | * This string is recognized by eserve and should be all lower case. |
| 50 | * This is how the editor detects that it is talking to NEdit instead |
| 51 | * of Vim, for example, when the connection is initiated from the editor. |
| 52 | * Examples: "nedit", "gvim" |
| 53 | */ |
| 54 | char *workshop_get_editor_name(); |
| 55 | |
| 56 | /* |
| 57 | * Version number of the editor. |
| 58 | * This number is communicated along with the protocol |
| 59 | * version to the application. |
| 60 | * Examples: "5.0.2", "19.3" |
| 61 | */ |
| 62 | char *workshop_get_editor_version(); |
| 63 | |
| 64 | |
| 65 | /* Goto a given line in a given file */ |
| 66 | void workshop_goto_line(char *filename, int lineno); |
| 67 | |
| 68 | |
| 69 | /* Set mark in a given file */ |
| 70 | void workshop_set_mark(char *filename, int lineno, int markId, int type); |
| 71 | |
| 72 | |
| 73 | /* Change mark type (for example from current-pc to pc-and-breakpoint) */ |
| 74 | void workshop_change_mark_type(char *filename, int markId, int type); |
| 75 | |
| 76 | /* |
| 77 | * Goto the given mark in a file (e.g. show it). |
| 78 | * If message is not null, display it in the footer. |
| 79 | */ |
| 80 | |
| 81 | void workshop_goto_mark(char *filename, int markId, char *message); |
| 82 | |
| 83 | |
| 84 | /* Delete mark */ |
| 85 | void workshop_delete_mark(char *filename, int markId); |
| 86 | |
| 87 | /* Begin/end pair of messages indicating that a series of _set_mark and |
| 88 | * _delete_mark messages will be sent. This can/should be used to suppress gui |
| 89 | * redraws between the begin and end messages. For example, if you switch |
| 90 | * to a headerfile that has a class breakpoint set, there may be hundreds |
| 91 | * of marks that need to be added. You don't want to refresh the gui for each |
| 92 | * added sign, you want to wait until the final end message. |
| 93 | */ |
| 94 | void workshop_mark_batch_begin(); |
| 95 | void workshop_mark_batch_end(); |
| 96 | |
| 97 | |
| 98 | /* Load a given file into the WorkShop buffer. "frameid" is a token string |
| 99 | * that identifies which frame the file would like to be loaded into. This |
| 100 | * will usually be null, in which case you should use the default frame. |
| 101 | * However, if frameid is not null, you need to find a frame that has this |
| 102 | * frameid, and replace the file in that frame. Finally, if the frameid is |
| 103 | * one you haven't seen before, you should create a new frame for this file. |
| 104 | * Note that "frameid" is a string value, not just an opaque pointer, so |
| 105 | * you should use strcmp rather than == when testing for equality. |
| 106 | */ |
| 107 | void workshop_load_file(char *filename, int line, char *frameid); |
| 108 | |
| 109 | |
| 110 | /* Reload the WorkShop buffer */ |
| 111 | void workshop_reload_file(char *filename, int line); |
| 112 | |
| 113 | |
| 114 | /* Show the given file */ |
| 115 | void workshop_show_file(char *filename); |
| 116 | |
| 117 | |
| 118 | /* Front the given file */ |
| 119 | void workshop_front_file(char *filename); |
| 120 | |
| 121 | |
| 122 | /* Save the given file */ |
| 123 | void workshop_save_file(char *filename); |
| 124 | |
| 125 | /* Save all WorkShop edited files. You can ask user about modified files |
| 126 | * and skip saving any files the user doesn't want to save. |
| 127 | * This function is typically called when the user issues a build, a fix, |
| 128 | * etc. (and also if you select "Save All" from the File menu :-) |
| 129 | */ |
| 130 | void workshop_save_files(); |
| 131 | |
| 132 | /* Show a message in all footers. |
| 133 | Severity currently is not defined. */ |
| 134 | void workshop_footer_message(char *message, int severity); |
| 135 | |
| 136 | /* Minimize all windows */ |
| 137 | void workshop_minimize(); |
| 138 | |
| 139 | |
| 140 | /* Maximize all windows */ |
| 141 | void workshop_maximize(); |
| 142 | |
| 143 | |
| 144 | /* |
| 145 | * Create a new mark type, assign it a given index, a given textbackground |
| 146 | * color, and a given left-margin sign (where sign is a filename to an |
| 147 | * .xpm file) |
| 148 | */ |
| 149 | void workshop_add_mark_type(int idx, char *colorspec, char *sign); |
| 150 | |
| 151 | |
| 152 | /* Get mark line number */ |
| 153 | int workshop_get_mark_lineno(char *filename, int markId); |
| 154 | |
| 155 | |
| 156 | /* Exit editor; save confirmation dialogs are okay */ |
| 157 | void workshop_quit(); |
| 158 | |
| 159 | /* Set an editor option. |
| 160 | * For example, name="syntax",value="on" would enable syntax highlighting. |
| 161 | * The currently defined options are: |
| 162 | * lineno {on,off} show line numbers |
| 163 | * syntax {on,off} highlight syntax |
| 164 | * parentheses {on,off} show matching parentheses |
| 165 | * The following options are interpreted by the library for you (so you |
| 166 | * will never see the message. However, the implementation requires you |
| 167 | * to provide certain callbacks, like restore hotkeys or save all files. |
| 168 | * These are documented separately). |
| 169 | * workshopkeys {on,off} set workshop hotkeys |
| 170 | * savefiles {on,off} save all files before issuing a build |
| 171 | * balloon {on,off} enable/disable balloon evaluate |
| 172 | * |
| 173 | * IGNORE an option if you do not recognize it. |
| 174 | */ |
| 175 | void workshop_set_option(char *name, char *value); |
| 176 | |
| 177 | /* |
| 178 | * (See workshop_add_frame first.) This function notifies the editor |
| 179 | * that the frame for the given window (indicated by "frame", which |
| 180 | * was supplied by the editor in workshop_add_frame) has been created. |
| 181 | * This can happen much later than the workshop_add_frame message, since |
| 182 | * often a window is created on editor startup, while the frame description |
| 183 | * is passed over from eserve much later, when the connection is complete. |
| 184 | * This gives the editor a chance to kick its GUI to show the frame |
| 185 | * properly; typically you'll unmanage and remanage the parent widget to |
| 186 | * force a geometry recalculation. |
| 187 | */ |
| 188 | |
| 189 | void workshop_reconfigure_frame(void *frame); |
| 190 | |
| 191 | |
| 192 | /* Are there any moved marks? If so, call workshop_move_mark on |
| 193 | * each of them now. This is how eserve can find out if for example |
| 194 | * breakpoints have moved when a program has been recompiled and |
| 195 | * reloaded into dbx. |
| 196 | */ |
| 197 | void workshop_moved_marks(char *filename); |
| 198 | |
| 199 | |
| 200 | /* A button in the toolbar has been pushed. "frame" is provided |
| 201 | * which should let you determine which toolbar had a button pushed |
| 202 | * (you supplied this clientData when you created a toolbar). From |
| 203 | * this you should be able to figure out which file the operation |
| 204 | * applies to, and for that window the cursor line and column, |
| 205 | * selection begin line and column, selection end line and column, |
| 206 | * selection text and selection text length. The column numbers are |
| 207 | * currently unused but implement it anyway in case we decide to use |
| 208 | * them in the future. |
| 209 | * Note that frame can be NULL. In this case, you should pick |
| 210 | * a default window to translate coordinates for (ideally, the |
| 211 | * last window the user has operated on.) This will be the case when |
| 212 | * the user clicks on a Custom Button programmed to take the current |
| 213 | * line number as an argument. Here it's ambiguous which buffer |
| 214 | * to use, so you need to pick one. |
| 215 | * (Interface consideration: Perhaps we instead should add smarts |
| 216 | * into the library such that we remember which frame pointer |
| 217 | * we last noticed (e.g. last call to get_positions, or perhaps |
| 218 | * last add_frame) and then pass that instead? For example, we could |
| 219 | * have all workshop operations return the clientData when passed |
| 220 | * the filename (or add a filename-to-clientData converter?) and then |
| 221 | * remember the last filename/clientData used. |
| 222 | */ |
| 223 | int workshop_get_positions(void *frame, |
| 224 | char **filename, |
| 225 | int *curLine, |
| 226 | int *curCol, |
| 227 | int *selStartLine, |
| 228 | int *selStartCol, |
| 229 | int *selEndLine, |
| 230 | int *selEndCol, |
| 231 | int *selLength, |
| 232 | char **selection); |
| 233 | |
| 234 | /* The following function should return the height of a character |
| 235 | * in the text display. This is used to pick out a suitable size |
| 236 | * for the signs to match the text (currently available in three |
| 237 | * sizes). If you just return 0, WorkShop will use the default |
| 238 | * sign size. (Use XmStringExtent on character "A" to get the height.) |
| 239 | */ |
| 240 | |
| 241 | int workshop_get_font_height(void); |
| 242 | |
| 243 | /* The following function requests that you register the given |
| 244 | * hotkey as a keyboard accelerator for all frames. Whenever the |
| 245 | * hotkey is pressed, you should invoke workshop_hotkey_pressed |
| 246 | * and pass the current frame pointer as an argument as well as |
| 247 | * the clientData pointer passed in to this function. |
| 248 | * The remove function unregisters the hotkey. |
| 249 | */ |
| 250 | void workshop_register_hotkey(Modifiers modifiers, KeySym keysym, |
| 251 | void *clientData); |
| 252 | void workshop_unregister_hotkey(Modifiers modifiers, KeySym keysym, |
| 253 | void *clientData); |
| 254 | |
| 255 | |
| 256 | |
| 257 | |
| 258 | /* |
| 259 | * |
| 260 | * The following functions notify eserve of important editor events, |
| 261 | * such as files being modified, files being saved, etc. You must |
| 262 | * sprinkle your editor code with calls to these. For example, whenever |
| 263 | * a file is modified (well, when its read-only status changes to modified), |
| 264 | * call workshop_file_modified(). |
| 265 | * |
| 266 | */ |
| 267 | |
| 268 | |
| 269 | |
| 270 | /* Connect with eserve. Add this call after you editor initialization |
| 271 | * is done, right before entering the event loop or blocking on input. |
| 272 | * This will set up a socket connection with eserve. |
| 273 | */ |
| 274 | void workshop_connect(XtAppContext context); |
| 275 | |
| 276 | /* A file has been opened. */ |
| 277 | void workshop_file_opened(char *filename, int readOnly); |
| 278 | |
| 279 | |
| 280 | /* A file has been saved. Despite its name, eserve also uses this |
| 281 | * message to mean a file has been reverted or unmodified. |
| 282 | */ |
| 283 | void workshop_file_saved(char *filename); |
| 284 | |
| 285 | |
Bram Moolenaar | fff2bee | 2010-05-15 13:56:02 +0200 | [diff] [blame] | 286 | #if 0 |
Bram Moolenaar | 071d427 | 2004-06-13 20:20:40 +0000 | [diff] [blame] | 287 | /* A file has been closed */ |
| 288 | void workshop_file_closed(char *filename); |
Bram Moolenaar | fff2bee | 2010-05-15 13:56:02 +0200 | [diff] [blame] | 289 | #endif |
Bram Moolenaar | 071d427 | 2004-06-13 20:20:40 +0000 | [diff] [blame] | 290 | |
| 291 | /* Like workshop_file_closed, but also inform eserve what line the |
| 292 | cursor was on when you left the file. That way eserve can put you |
| 293 | back where you left off when you return to this file. */ |
| 294 | void workshop_file_closed_lineno(char *filename, int line); |
| 295 | |
Bram Moolenaar | fff2bee | 2010-05-15 13:56:02 +0200 | [diff] [blame] | 296 | #if 0 |
Bram Moolenaar | 071d427 | 2004-06-13 20:20:40 +0000 | [diff] [blame] | 297 | /* A file has been modified */ |
| 298 | void workshop_file_modified(char *filename); |
| 299 | |
Bram Moolenaar | 071d427 | 2004-06-13 20:20:40 +0000 | [diff] [blame] | 300 | /* |
| 301 | * A mark has been moved. Only call this as a response to |
| 302 | * a workshop_moved_marks request call. |
| 303 | */ |
| 304 | void workshop_move_mark(char *filename, int markId, int newLineno); |
Bram Moolenaar | fff2bee | 2010-05-15 13:56:02 +0200 | [diff] [blame] | 305 | #endif |
Bram Moolenaar | 071d427 | 2004-06-13 20:20:40 +0000 | [diff] [blame] | 306 | |
| 307 | /* Tell the integration library about a new frame being added. |
| 308 | * Supply a form for the toolbar, a label for the footer, and an |
| 309 | * XmPulldown menu for the WorkShop menu to attach to. Top and bottom |
| 310 | * are the widgets above and below the toolbar form widget, if |
| 311 | * any. Call this function when you create a new window. It returns a |
| 312 | * void *, a handle which you should keep and return when you delete |
| 313 | * the window with workshop_delete_toolbar. The "footer" argument |
| 314 | * points to a Label widget that is going to be used as a status |
| 315 | * message area, and "menu" (if any) points to an Menu widget that |
| 316 | * should contain a WorkShop menu. Clientdata is a pointer which is |
| 317 | * only used by the editor. It will typically be a pointer to the |
| 318 | * window object that the toolbar is placed in. If you have multiple |
| 319 | * windows, you need to use this pointer to figure out which window |
| 320 | * (and thus corresponding buffer) the user has clicked on to respond |
| 321 | * to the workshop_get_positions message. |
| 322 | * Each frame's clientData ("frame") should be unique. |
| 323 | */ |
| 324 | void *workshop_add_frame(void *frame, Widget form, |
| 325 | Widget top, Widget bottom, Widget footer, |
| 326 | Widget menu); |
| 327 | |
| 328 | /* Delete a window/frame. Call this when an editor window is being deleted. */ |
| 329 | void workshop_delete_frame(void *handle); |
| 330 | |
| 331 | /* Add a balloon evaluate text area. "frame" is used the same way |
| 332 | * as in workshop_add_frame. This call is not part of workshop_add_frame because |
| 333 | * a frame can have multiple tooltip areas (typically, an editor frame that |
| 334 | * is split showing multiple buffers will have a separate tooltip area for |
| 335 | * each text widget. Each such area is called a "window" (consistent with |
| 336 | * XEmacs terminology). Separate these by the window argument if necessary. |
| 337 | * You will need to implement workshop_get_balloon_text such that it uses |
| 338 | * these two arguments to derive the file, line etc. for the tip. |
| 339 | * Call the remove function if you delete this area such that the integration |
| 340 | * library can update itself. You must call workshop_add_frame before you |
| 341 | * call add_balloon_eval_area, and you must pass the same frame pointer. |
| 342 | */ |
| 343 | void workshop_add_balloon_eval_area(void *frame, void *window, Widget widget); |
| 344 | void workshop_remove_balloon_eval_area(void *frame, void *window, Widget widget); |
| 345 | |
| 346 | |
| 347 | /* For a given mouse position inside the balloon area (passed as x,y), |
| 348 | * return the balloon text to be evaluated. There are two scenarios: |
| 349 | * If the position is inside the selection, return the selection |
| 350 | * string. Else, return the full line (or possibly the full line up |
| 351 | * to the last semicolon (that's TBD), along with an index pointing to |
| 352 | * where which character the mouse is over. |
| 353 | * If we have the selection-scenario, set mouseIndex to -1 to indicate |
| 354 | * that no autoexpansion should occur but that the selection should |
| 355 | * be evaluated as is. |
| 356 | * |
| 357 | * XXX Does dbx need more information here, like the filename and line |
| 358 | * number in order to determine the correct language and scope to be |
| 359 | * used during evaluation?? Or should it just work like the p= button |
| 360 | * (where the current scope and language is used, even if you are |
| 361 | * pointing at a different file with a different scope) ? |
| 362 | */ |
| 363 | int workshop_get_balloon_text(Position x, Position y, |
| 364 | void *frame, |
| 365 | void *window, |
| 366 | char **filename, |
| 367 | int *line, |
| 368 | char **text, |
| 369 | int *mouseIndex); |
| 370 | |
| 371 | |
| 372 | /* Window size and location |
| 373 | * WorkShop will attempt to restore the size and location of a single |
| 374 | * editor frame. For vi, this window is designated as the "reusable" one. |
| 375 | * You can implement your own scheme for determining which window you |
| 376 | * want to associate with WorkShop. Whenever the size and location of |
| 377 | * this window is changed, call the following function to notify eserve. |
| 378 | * Like workshop_invoked, this can be called before the workshop_connect() |
| 379 | * call. |
| 380 | */ |
| 381 | void workshop_frame_moved(int new_x, int new_y, int new_w, int new_h); |
| 382 | Boolean workshop_get_width_height(int *, int *); |
Bram Moolenaar | fff2bee | 2010-05-15 13:56:02 +0200 | [diff] [blame] | 383 | #if 0 |
Bram Moolenaar | 071d427 | 2004-06-13 20:20:40 +0000 | [diff] [blame] | 384 | Boolean workshop_get_rows_cols(int *, int *); |
Bram Moolenaar | fff2bee | 2010-05-15 13:56:02 +0200 | [diff] [blame] | 385 | #endif |
Bram Moolenaar | 071d427 | 2004-06-13 20:20:40 +0000 | [diff] [blame] | 386 | |
| 387 | /* This function should be invoked when you press a hotkey |
| 388 | * set up by workshop_register_hotkey. Pass the clientData |
| 389 | * to it that was given to you with workshop_register_hotkey. |
| 390 | */ |
| 391 | void workshop_hotkey_pressed(void *frame, void *clientData); |
| 392 | |
| 393 | |
| 394 | |
| 395 | |
| 396 | |
| 397 | /* |
| 398 | * Utility functions |
| 399 | * These provide convenience functions to simplify implementing some |
| 400 | * of the above functions. |
| 401 | * |
| 402 | */ |
| 403 | |
Bram Moolenaar | fff2bee | 2010-05-15 13:56:02 +0200 | [diff] [blame] | 404 | #if 0 |
Bram Moolenaar | 071d427 | 2004-06-13 20:20:40 +0000 | [diff] [blame] | 405 | /* Were we invoked by WorkShop? This function can be used early during startup |
| 406 | * if you want to do things differently if the editor is started standalone |
| 407 | * or in WorkShop mode. For example, in standalone mode you may not want to |
| 408 | * add a footer/message area or a sign gutter. |
| 409 | */ |
| 410 | int workshop_invoked(void); |
Bram Moolenaar | fff2bee | 2010-05-15 13:56:02 +0200 | [diff] [blame] | 411 | #endif |
Bram Moolenaar | 071d427 | 2004-06-13 20:20:40 +0000 | [diff] [blame] | 412 | |
Bram Moolenaar | 071d427 | 2004-06-13 20:20:40 +0000 | [diff] [blame] | 413 | |
| 414 | /* Minimize (iconify) the given shell */ |
| 415 | void workshop_minimize_shell(Widget shell); |
| 416 | |
| 417 | /* Maximize (deiconify) the given shell */ |
| 418 | void workshop_maximize_shell(Widget shell); |
| 419 | |
| 420 | /* Called by frame.cc -- editor shouldn't call this directly. |
| 421 | * Perhaps we need an integrationP.h file ? */ |
| 422 | void workshop_perform_verb(char *verb, void *clientData); |
| 423 | void workshop_send_message(char *buf); |
| 424 | |
| 425 | |
| 426 | #ifdef NOHANDS_SUPPORT_FUNCTIONS |
| 427 | /* The following functions are needed to run the WorkShop testsuite |
| 428 | * with this editor. You don't need to implement these unless you |
| 429 | * intend for your editor to be run by Workshop's testsuite. |
| 430 | * getcursorrow should return the number of lines from the top of |
| 431 | * the window the cursor is; similarly for getcursorcol. |
| 432 | */ |
| 433 | char *workshop_test_getcurrentfile(); |
| 434 | int workshop_test_getcursorrow(); |
| 435 | int workshop_test_getcursorcol(); |
| 436 | char *workshop_test_getcursorrowtext(); |
| 437 | char *workshop_test_getselectedtext(); |
| 438 | #endif |
| 439 | |
| 440 | /* |
| 441 | * Struct used to set/unset the sensitivity of verbs. |
| 442 | */ |
| 443 | typedef struct { |
| 444 | char *verb; |
| 445 | Boolean sense; |
| 446 | } VerbSense; |
| 447 | |
| 448 | #ifdef __cplusplus |
| 449 | } |
| 450 | #endif |
| 451 | |
| 452 | #endif /* _INTEGRATION_H */ |