1/* Part of SWI-Prolog 2 3 Author: Jan Wielemaker 4 E-mail: J.Wielemaker@vu.nl 5 WWW: http://www.swi-prolog.org 6 Copyright (c) 2002-2015, University of Amsterdam 7 VU University Amsterdam 8 All rights reserved. 9 10 Redistribution and use in source and binary forms, with or without 11 modification, are permitted provided that the following conditions 12 are met: 13 14 1. Redistributions of source code must retain the above copyright 15 notice, this list of conditions and the following disclaimer. 16 17 2. Redistributions in binary form must reproduce the above copyright 18 notice, this list of conditions and the following disclaimer in 19 the documentation and/or other materials provided with the 20 distribution. 21 22 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 23 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 24 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 25 FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 26 COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 27 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 28 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 29 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 30 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 32 ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 33 POSSIBILITY OF SUCH DAMAGE. 34*/ 35 36:- module(win_menu, 37 [ init_win_menus/0 38 ]). 39:- use_module(library(lists)). 40:- use_module(library(apply)). 41:- use_module(library(error)). 42:- set_prolog_flag(generate_debug_info, false). 43:- op(200, fy, @). 44:- op(990, xfx, :=).
52:- if(current_prolog_flag(console_menu_version, qt)). 53% The traditional swipl-win.exe predefines some menus. The Qt version 54% does not. Here, we predefine the same menus to make the remainder 55% compatiple. '&File', 57 [ 'E&xit' = pqConsole:quit_console 58 ], 59 [ 60 ]) (. 61menu('&Edit', 62 [ '&Copy' = pqConsole:copy, 63 '&Paste' = pqConsole:paste 64 ], 65 []). 66menu('&Settings', 67 [ '&Font ...' = pqConsole:select_font, 68 '&Colors ...' = pqConsole:select_ANSI_term_colors 69 ], 70 []). 71menu('&Run', 72 [ '&Interrupt' = interrupt, 73 '&New thread' = interactor 74 ], 75 []). 76 77menu(File, 78 [ '&Consult ...' = action(user:load_files(+file(open, 79 'Load file into Prolog'), 80 [silent(false)])), 81 '&Edit ...' = action(user:edit(+file(open, 82 'Edit existing file'))), 83 '&New ...' = action(edit_new(+file(save, 84 'Create new Prolog source'))), 85 -- 86 | MRU 87 ], [before_item('E&xit')]) :- 88 File = '&File', 89 findall(Mru=true, mru_info(File, Mru, _, _, _), MRU, MRUTail), 90 MRUTail = [ --, 91 '&Reload modified files' = user:make, 92 --, 93 '&Navigator ...' = prolog_ide(open_navigator), 94 -- 95 ]. 96 97:- else. 98 99menu('&File', 100 [ '&Consult ...' = action(user:consult(+file(open, 101 'Load file into Prolog'))), 102 '&Edit ...' = action(user:edit(+file(open, 103 'Edit existing file'))), 104 '&New ...' = action(edit_new(+file(save, 105 'Create new Prolog source'))), 106 --, 107 '&Reload modified files' = user:make, 108 --, 109 '&Navigator ...' = prolog_ide(open_navigator), 110 -- 111 ], 112 [ before_item('&Exit') 113 ]). 114:- endif. 115 116menu('&Settings', 117 [ --, 118 '&User init file ...' = prolog_edit_preferences(prolog), 119 '&GUI preferences ...' = prolog_edit_preferences(xpce) 120 ], 121 []). 122menu('&Debug', 123 [ %'&Trace' = trace, 124 %'&Debug mode' = debug, 125 %'&No debug mode' = nodebug, 126 '&Edit spy points ...' = user:prolog_ide(open_debug_status), 127 '&Edit exceptions ...' = user:prolog_ide(open_exceptions(@on)), 128 '&Threads monitor ...' = user:prolog_ide(thread_monitor), 129 'Debug &messages ...' = user:prolog_ide(debug_monitor), 130 'Cross &referencer ...'= user:prolog_ide(xref), 131 --, 132 '&Graphical debugger' = user:guitracer 133 ], 134 [ before_menu(-) 135 ]). 136menu('&Help', 137 [ '&About ...' = about, 138 '&Help ...' = help, 139 'Browse &PlDoc ...' = doc_browser, 140 --, 141 'SWI-Prolog website ...' = www_open(swipl), 142 ' &Manual ...' = www_open(swipl_man), 143 ' &FAQ ...' = www_open(swipl_faq), 144 ' &Quick Start ...' = www_open(swipl_quick), 145 ' Mailing &List ...' = www_open(swipl_mail), 146 ' &Download ...' = www_open(swipl_download), 147 ' &Extension packs ...' = www_open(swipl_pack), 148 --, 149 '&XPCE (GUI) Manual ...' = manpce, 150 --, 151 '&Check installation' = check_installation, 152 'Submit &Bug report ...' = www_open(swipl_bugs) 153 ], 154 [ before_menu(-) 155 ]). 156 157 :- 159 ( menu(Menu, Items, Options), 160 ( memberchk(before_item(Before), Options) 161 -> true 162 ; Before = (-) 163 ), 164 ( memberchk(before_menu(BM), Options) 165 -> true 166 ; BM = (-) 167 ), 168 win_insert_menu(Menu, BM), 169 ( '$member'(Item, Items), 170 ( Item = (Label = Action) 171 -> true 172 ; Item == -- 173 -> Label = -- 174 ), 175 win_insert_menu_item(Menu, Label, Before, Action), 176 fail 177 ; true 178 ), 179 fail 180 ; current_prolog_flag(associated_file, File), 181 add_to_mru(load, File) 182 ; insert_associated_file 183 ), 184 refresh_mru. 185 186associated_file(File) :- 187 current_prolog_flag(associated_file, File), 188 !. 189associated_file(File) :- 190 '$cmd_option_val'(script_file, OsFiles), 191 OsFiles = [OsFile], 192 !, 193 prolog_to_os_filename(File, OsFile). 194 195insert_associated_file :- 196 associated_file(File), 197 !, 198 file_base_name(File, Base), 199 atom_concat('Edit &', Base, Label), 200 win_insert_menu_item('&File', Label, '&New ...', edit(file(File))). 201insert_associated_file. 202 203 204:- if(current_predicate(win_has_menu/0)). 205:- initialization 206 ( win_has_menu 207 -> init_win_menus 208 ; true 209 ). 210:- endif. 211 212 /******************************* 213 * ACTIONS * 214 *******************************/ 215 216edit_new(File) :- 217 call(edit(file(File))). % avoid autoloading 218 219www_open(Id) :- 220 Spec =.. [Id, '.'], 221 call(expand_url_path(Spec, URL)), 222 print_message(informational, opening_url(URL)), 223 call(www_open_url(URL)), % avoid autoloading 224 print_message(informational, opened_url(URL)). 225 226html_open(Spec) :- 227 absolute_file_name(Spec, [access(read)], Path), 228 call(win_shell(open, Path)). 229 230:- if(current_predicate(win_message_box/2)). 231 232about :- 233 message_to_string(about, AboutSWI), 234 ( current_prolog_flag(console_menu_version, qt) 235 -> message_to_string(about_qt, AboutQt), 236 format(atom(About), '<p>~w\n<p>~w', [AboutSWI, AboutQt]) 237 ; About = AboutSWI 238 ), 239 atomic_list_concat(Lines, '\n', About), 240 atomic_list_concat(Lines, '<br>', AboutHTML), 241 win_message_box( 242 AboutHTML, 243 [ title('About swipl-win'), 244 image(':/swipl.png'), 245 min_width(700) 246 ]). 247 248:- else. 249 250about :- 251 print_message(informational, about). 252 253:- endif. 254 255load(Path) :- 256 ( \+ current_prolog_flag(associated_file, _) 257 -> file_directory_name(Path, Dir), 258 working_directory(_, Dir), 259 set_prolog_flag(associated_file, Path) 260 ; true 261 ), 262 user:load_files(Path). 263 264 265 /******************************* 266 * HANDLE CALLBACK * 267 *******************************/ 268 269action(Action) :- 270 strip_module(Action, Module, Plain), 271 Plain =.. [Name|Args], 272 gather_args(Args, Values), 273 Goal =.. [Name|Values], 274 call(Module:Goal). 275 276gather_args([], []). 277gather_args([+H0|T0], [H|T]) :- 278 !, 279 gather_arg(H0, H), 280 gather_args(T0, T). 281gather_args([H|T0], [H|T]) :- 282 gather_args(T0, T). 283 284:- if(current_prolog_flag(console_menu_version, qt)). 285 286gather_arg(file(open, Title), File) :- 287 !, 288 source_types_desc(Desc), 289 pqConsole:getOpenFileName(Title, _, Desc, File), 290 add_to_mru(edit, File). 291 292gather_arg(file(save, Title), File) :- 293 source_types_desc(Desc), 294 pqConsole:getSaveFileName(Title, _, Desc, File), 295 add_to_mru(edit, File). 296 297source_types_desc(Desc) :- 298 findall(Pattern, prolog_file_pattern(Pattern), Patterns), 299 atomic_list_concat(Patterns, ' ', Atom), 300 format(atom(Desc), 'Prolog Source (~w)', [Atom]). 301 302:- else. 303 304gather_arg(file(Mode, Title), File) :- 305 findall(tuple('Prolog Source', Pattern), 306 prolog_file_pattern(Pattern), 307 Tuples), 308 '$append'(Tuples, [tuple('All files', '*.*')], AllTuples), 309 Filter =.. [chain|AllTuples], 310 current_prolog_flag(hwnd, HWND), 311 working_directory(CWD, CWD), 312 call(get(@display, win_file_name, % avoid autoloading 313 Mode, Filter, Title, 314 directory := CWD, 315 owner := HWND, 316 File)). 317 318:- endif. 319 320prolog_file_pattern(Pattern) :- 321 user:prolog_file_type(Ext, prolog), 322 atom_concat('*.', Ext, Pattern). 323 324 325:- if(current_prolog_flag(windows, true)). 326 327 /******************************* 328 * APPLICATION * 329 *******************************/
336init_win_app :- 337 current_prolog_flag(associated_file, _), 338 !. 339init_win_app :- 340 '$cmd_option_val'(win_app, true), 341 !, 342 catch(my_prolog, E, print_message(warning, E)). 343init_win_app. 344 345my_prolog :- 346 win_folder(personal, MyDocs), 347 atom_concat(MyDocs, '/Prolog', PrologDir), 348 ( ensure_dir(PrologDir) 349 -> working_directory(_, PrologDir) 350 ; working_directory(_, MyDocs) 351 ). 352 353 354ensure_dir(Dir) :- 355 exists_directory(Dir), 356 !. 357ensure_dir(Dir) :- 358 catch(make_directory(Dir), E, (print_message(warning, E), fail)). 359 360 361:- initialization 362 init_win_app. 363 364:- endif. /*windows*/ 365 366 367 /******************************* 368 * MacOS * 369 *******************************/ 370 371:- if(current_prolog_flag(console_menu_version, qt)). 372 373:- multifile 374 prolog:file_open_event/1. 375 376:- create_prolog_flag(app_open_first, load, []). 377:- create_prolog_flag(app_open, edit, []).
app_open_first
defines the action for the first open eventapp_open
defines the action for subsequent open eventOn the first open event, the working directory of the process is changed to the directory holding the file. Action is one of the following:
399prologfile_open_event(Path) :- 400 ( current_prolog_flag(associated_file, _) 401 -> current_prolog_flag(app_open, Action) 402 ; current_prolog_flag(app_open_first, Action), 403 file_directory_name(Path, Dir), 404 working_directory(_, Dir), 405 set_prolog_flag(associated_file, Path), 406 insert_associated_file 407 ), 408 must_be(oneof([edit,load,new_instance]), Action), 409 file_open_event(Action, Path). 410 411file_open_event(edit, Path) :- 412 edit(Path). 413file_open_event(load, Path) :- 414 add_to_mru(load, Path), 415 user:load_files(Path). 416:- if(current_prolog_flag(apple, true)). 417file_open_event(new_instance, Path) :- 418 current_app(Me), 419 print_message(informational, new_instance(Path)), 420 process_create(path(open), [ '-n', '-a', Me, Path ], []). 421:- else. 422file_open_event(new_instance, Path) :- 423 current_prolog_flag(executable, Exe), 424 process_create(Exe, [Path], [process(_Pid)]). 425:- endif. 426 427 428:- if(current_prolog_flag(apple, true)). 429current_app(App) :- 430 current_prolog_flag(executable, Exe), 431 file_directory_name(Exe, MacOSDir), 432 atom_concat(App, '/Contents/MacOS', MacOSDir).
439go_home_on_plain_app_start :- 440 current_prolog_flag(os_argv, [_Exe]), 441 current_app(App), 442 file_directory_name(App, Above), 443 working_directory(PWD, PWD), 444 same_file(PWD, Above), 445 expand_file_name(~, [Home]), 446 !, 447 working_directory(_, Home). 448go_home_on_plain_app_start. 449 450:- initialization 451 go_home_on_plain_app_start. 452 453:- endif. 454:- endif. 455 456:- if(current_predicate(win_current_preference/3)). 457 458mru_info('&File', 'Edit &Recent', 'MRU2', path, edit). 459mru_info('&File', 'Load &Recent', 'MRULoad', path, load). 460 461add_to_mru(Action, File) :- 462 mru_info(_Top, _Menu, PrefGroup, PrefKey, Action), 463 ( win_current_preference(PrefGroup, PrefKey, CPs), nonvar(CPs) 464 -> ( select(File, CPs, Rest) 465 -> Updated = [File|Rest] 466 ; length(CPs, Len), 467 Len > 10 468 -> append(CPs1, [_], CPs), 469 Updated = [File|CPs1] 470 ; Updated = [File|CPs] 471 ) 472 ; Updated = [File] 473 ), 474 win_set_preference(PrefGroup, PrefKey, Updated), 475 refresh_mru. 476 477refresh_mru :- 478 ( mru_info(FileMenu, Menu, PrefGroup, PrefKey, Action), 479 win_current_preference(PrefGroup, PrefKey, CPs), 480 maplist(action_path_menu(Action), CPs, Labels, Actions), 481 win_insert_menu_item(FileMenu, Menu/Labels, -, Actions), 482 fail 483 ; true 484 ). 485 ActionItem, Path, Label, win_menu:Action) (:- 487 file_base_name(Path, Label), 488 Action =.. [ActionItem, Path]. 489 490:- else. 491 492add_to_mru(_, _). 493refresh_mru. 494 495:- endif. 496 497 498 /******************************* 499 * MESSAGES * 500 *******************************/ 501 502:- multifile 503 prolog:message/3. 504 505prologmessage(opening_url(Url)) --> 506 [ 'Opening ~w ... '-[Url], flush ]. 507prologmessage(opened_url(_Url)) --> 508 [ at_same_line, 'ok' ]. 509prologmessage(new_instance(Path)) --> 510 [ 'Opening new Prolog instance for ~p'-[Path] ]. 511:- if(current_prolog_flag(console_menu_version, qt)). 512prologmessage(about_qt) --> 513 [ 'Qt-based console by Carlo Capelli' ]. 514:- endif.
Console window menu
This library sets up the menu of swipl-win.exe. It is called from the system initialisation file
plwin-win.rc
, predicate gui_setup_/0. */