source: trunk/src/netlabs/macros/keys.e

Last change on this file was 5227, checked in by Andreas Schnellbacher, 2 years ago
  • Property svn:keywords set to Date Revision Author HeadURL Id
File size: 206.3 KB
Line 
1/****************************** Module Header *******************************
2*
3* Module Name: keys.e
4*
5* Copyright (c) Netlabs EPM Distribution Project 2002
6*
7* $Id: keys.e 5227 2022-11-23 09:01:15Z aschn $
8*
9* ===========================================================================
10*
11* This file is part of the Netlabs EPM Distribution package and is free
12* software. You can redistribute it and/or modify it under the terms of the
13* GNU General Public License as published by the Free Software
14* Foundation, in version 2 as it comes in the "COPYING" file of the
15* Netlabs EPM Distribution. This library is distributed in the hope that it
16* will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
17* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18* General Public License for more details.
19*
20****************************************************************************/
21
22compile if not defined( SMALL) -- If compiled separately
23 EA_comment 'This defines definitions for keysets.'
24
25define
26 INCLUDING_FILE = 'KEYS.E'
27
28 include 'stdconst.e'
29const
30 tryinclude 'mycnf.e'
31const
32 compile if not defined( NLS_LANGUAGE)
33 NLS_LANGUAGE = 'ENGLISH'
34 compile endif
35 include NLS_LANGUAGE'.e'
36
37; In case someone executes 'keys' by mistake, the module would be unlinked.
38; Therefore add a (nop) defc that would be executed then in preference:
39defc keys
40 -- nop
41compile endif
42
43; ---------------------------------------------------------------------------
44definit
45 universal blockreflowflag
46
47 blockreflowflag = 0
48compile if defined(ACTIONS_ACCEL__L) -- For CUSTEPM support
49 call AddMenuAVar( 'usedmenuaccelerators', 'A')
50compile endif
51compile if defined(TEX_BAR__MSG) -- For TFE or EPMTeX support
52 call AddMenuAVar( 'usedmenuaccelerators', 'T')
53compile endif
54compile if defined(ECO_MENU__MSG) -- For ECO support
55 call AddMenuAVar( 'usedmenuaccelerators', 'I')
56compile endif
57
58 -- These keys must be defined as WM_CHAR keys, not as accelerator keys.
59 -- Otherwise typing single accent keys like ^ï` and entering a char via
60 -- its key code with Alt and the keypad numbers won't work.
61 -- This array var value must be specified in lowercase and with the
62 -- underscore as prefix separator: c_, a_ or s_ (not + or -)
63 NonAccelKeys = ''
64 NonAccelKeys = NonAccelKeys' a_1 a_2 a_3 a_4 a_5 a_6 a_7 a_8 a_9 a_0'
65 NonAccelKeys = NonAccelKeys' space'
66 NonAccelKeys = NonAccelKeys' down up left right'
67 NonAccelKeys = NonAccelKeys' a_down a_up a_left a_right'
68 NonAccelKeys = NonAccelKeys' a_ins a_del a_home a_end a_pgdn a_pgup'
69 call AddKeysAVar( 'nonaccelkeys', NonAccelKeys)
70
71; ---------------------------------------------------------------------------
72; Apparently edit_keys must be defined in EPM.EX as first ETK keyset.
73; Therefore "defkeys edit_keys new clear" was moved to INIT.E to be
74; included early.
75;
76; The standard ETK keyset "edit_keys" is mainly a dummy keyset, compared to
77; the original EPM keyset definition. It defines all keys as otherkeys,
78; except a_0 ... a_9, which are not executable as accel keys without unwanted
79; results.
80;
81; Otherkeys processes all keys for which no accel key def exists. That are
82; mainly single char keys. Process_Key works like Keyin, but handles
83; overwriting of the marked area in CUA marking mode.
84;
85; Bug in EPM's ETK keyset handling:
86; .keyset = '<new_keyset>' works only, if <new_keyset> was defined in
87; the same .EX file, from where the keyset should be changed.
88; Therefore (as a workaround) switch temporarily to the externally
89; defined keyset in order to make it known for 'SetKeys':
90;
91; definit -- required for a separately compiled package
92; saved_keys = .keyset
93; .keyset = '<new_keyset>'
94; .keyset = saved_keys
95;
96; Note: An .EX file, that defines a keyset, can't be unlinked, when this
97; keyset is in use.
98
99; ---------------------------------------------------------------------------
100/***
101; The following is defined in INIT.E and is processed during definit of
102; EPM.E.
103
104; This defines the standard keyset. It's important to use the option 'clear'.
105; Otherwise otherkeys won't process the standard letters, numbers and chars.
106;
107; The keyset 'edit_keys' must be defined before all other keysets.
108; Therefore this file is actually included early in EPM.E. It's possible to
109; link these defs, but then other key defs must be linked after defining
110; 'edit_keys'.
111; (To do: test if defs from 'edit_keys' are overtaken by other keysets then.)
112defkeys edit_keys new clear
113
114; For testing:
115;def '„'
116; dprintf( 'lastkey() = 'lastkey()', ch = 'ch)
117; call SaveKeyCmd( lastkey())
118; call Process_Keys( 'ae')
119
120; Alt+0 ... Alt+9 keys (WM_CHAR):
121; These standard key defs are not executed as accel keys in order to keep
122; entering a char via Alt+keypad key working.
123; Because accel keys don't create a WM_CHAR message, they can't be handled
124; by lastkey or getkeystate.
125; To assign code to these keys, they have to be additionally defined via the
126; DefKey proc (which is used for defining accel keys). DefKey handles them
127; specially: It sets just an array var, that is queried and executed by
128; ExecKeyCmd.
129def a_1 'ExecKeyCmd a_1'
130def a_2 'ExecKeyCmd a_2'
131def a_3 'ExecKeyCmd a_3'
132def a_4 'ExecKeyCmd a_4'
133def a_5 'ExecKeyCmd a_5'
134def a_6 'ExecKeyCmd a_6'
135def a_7 'ExecKeyCmd a_7'
136def a_8 'ExecKeyCmd a_8'
137def a_9 'ExecKeyCmd a_9'
138def a_0 'ExecKeyCmd a_0'
139
140; Space key (WM_CHAR):
141; In order to type the single accent key '^' which is created by
142; <hat_key>+<space>, space must not be defined as accel key. Therefore
143; Space is defined with ExecKeyCmd. That means that it executes the
144; command that is stored by DefKey( Space, cmd) as an array var.
145def space 'ExecKeyCmd space'
146
147; Cursor keys (WM_CHAR):
148; When processed as accel keys, cursor key messages send by another app
149; are ignored. This happens if AMouse is configured to send keyboard
150; messages instead of scroll window messages.
151def down 'ExecKeyCmd down'
152def up 'ExecKeyCmd up'
153def left 'ExecKeyCmd left'
154def right 'ExecKeyCmd right'
155
156; Processing the keys above in the 'otherkeys' command would work, but
157; their scancode may vary with different keyboard layouts. The E toolkit
158; key names (used after 'def') handle that.
159
160; Add more keys here that have to be processed as standard E toolkit keys
161; or can't be processed as accelerator keys. The cursor keys above are
162; defined as both. When being processed, the accel def wins. To ignore
163; the accel def, a key must be added to the 'noaccelkeys' array var above.
164
165; OtherKeys processes all other single keys plus those virtual keys that
166; are also defined as number keys on the keypad block (WM_CHAR):
167def otherkeys
168 'OtherKeys' -- Defined in KEYS.E
169***/
170
171; ---------------------------------------------------------------------------
172defproc CtrlIsDown
173 ks = getkeystate( VK_CTRL)
174 fDown = (ks = 1 | ks = 2)
175 return fDown
176
177; ---------------------------------------------------------------------------
178defproc AltIsDown
179 ks = getkeystate( VK_ALT)
180 fDown = (ks = 1 | ks = 2)
181 return fDown
182
183; ---------------------------------------------------------------------------
184defproc ShiftIsDown
185 ks = getkeystate( VK_SHIFT)
186 fDown = (ks = 1 | ks = 2)
187 return fDown
188
189; ---------------------------------------------------------------------------
190; This is used to separate standard char keys from modifier keys
191; (Ctrl/Alt/Sh) and virtual keys.
192defproc IsSingleKey
193 k = arg( 1)
194 fSingle = 0
195 -- This can't work on DBCS systems:
196 if length( k) = 1 then
197 fSingle = 1
198 -- This should work on DBCS systems:
199 elseif IsDbcs( k) then
200 fSingle = 1
201 endif
202 return fSingle
203
204; ---------------------------------------------------------------------------
205; OtherKeys processes all other single keys plus those Alt+virtual keys that
206; are also defined as number keys on the keypad block (WM_CHAR).
207defc OtherKeys
208 k = lastkey()
209 parse value lastkey( 2) with Flags 3 Repeat 4 ScanCode 5 CharCode 7 VkCode 9
210 ScanCode = Hex2Dec( c2x( ScanCode))
211 VkCode = itoa( VkCode, 10)
212
213 fExpanded = 0
214
215 if IsSingleKey( k) then
216
217 call SaveKeyCmd( k)
218
219 fExpanded = ExpandKey()
220 if fExpanded = 0 then
221 call Process_Key( k)
222 endif
223
224 elseif AltIsDown() then
225 -- Filter out keypad keys in order to keep entering a char via
226 -- Alt+keypad key working.
227 -- Usually keypad keys have a decimal scancode < 95. The scancode is
228 -- hardware-specific. The following line has to be changed for other
229 -- unusual keyboards.
230 -- The scancode (in hex) can be shown both in a PMPrintf window and
231 -- on EPM's mesageline by the TestKeys command.
232 if ScanCode >= 95 then
233
234 if VkCode = VK_UP then
235 'ExecKeyCmd a_up'
236 elseif VkCode = VK_DOWN then
237 'ExecKeyCmd a_down'
238 elseif VkCode = VK_LEFT then
239 'ExecKeyCmd a_left'
240 elseif VkCode = VK_RIGHT then
241 'ExecKeyCmd a_right'
242 elseif VkCode = VK_INSERT then
243 'ExecKeyCmd a_ins'
244 elseif VkCode = VK_DELETE then
245 'ExecKeyCmd a_del'
246 elseif VkCode = VK_HOME then
247 'ExecKeyCmd a_home'
248 elseif VkCode = VK_END then
249 'ExecKeyCmd a_end'
250 elseif VkCode = VK_PAGEDOWN then
251 'ExecKeyCmd a_pgdn'
252 elseif VkCode = VK_PAGEUP then
253 'ExecKeyCmd a_pgup'
254 endif
255
256 endif
257 endif
258
259; ---------------------------------------------------------------------------
260; Standard key defs don't work for keypad keys, only for normal keys.
261; Therefore keypad keys don't have to be filtered out here.
262; Keypad keys can be redefined via accel keys, but then entering chars by
263; entering its keycode via Alt+keypad keys won't work anymore.
264defc ExecKeyCmd
265 -- The array var is internally set by the DefKey proc if Alt+num keys
266 -- were defined via DefKey.
267 KeyString = arg( 1)
268 Cmd = GetKeysAVar( 'keydef.'KeyString)
269
270 call SaveKeyCmd( KeyString''\1''Cmd)
271 fExpanded = ExpandKey()
272 --dprintf( 'ExecKeyCmd: KeyString = 'KeyString', fExpanded = 'fExpanded)
273
274 if fExpanded = 0 then
275 if Cmd <> '' then
276 Cmd
277 else
278 k = lastkey()
279 call Process_Key( k)
280 endif
281 endif
282
283; ---------------------------------------------------------------------------
284; This ignores modifier key combinations. Therefore it can be used for single
285; chars only.
286defproc Process_Key( char)
287 if IsSingleKey( char) & char <> \0 then
288 call Process_Keys( char)
289 endif
290
291; ---------------------------------------------------------------------------
292; This types one or multiple chars. It handles replacing a marked area while
293; CUA marking is active.
294defproc Process_Keys( chars)
295 universal lastcommand
296
297 fInsert = insertstate()
298 fMarked = 0
299 fInsertToggled = 0
300 fMarkDeleted = (ReplaceMark() = 1)
301 if not fInsert & fMarkDeleted then
302 -- Turn on insert mode because the key should replace
303 -- the mark, not the character after the mark.
304 inserttoggle
305 fInsertToggled = 1
306 endif
307 lastcommand = chars
308
309 keyin chars
310
311 if fInsertToggled then
312 inserttoggle
313 endif
314
315; ---------------------------------------------------------------------------
316; An easier to remember synonym for Process_Keys.
317defproc TypeChars( chars)
318 call Process_Keys( chars)
319
320; ---------------------------------------------------------------------------
321; Defined as command for use in key definition files.
322defc TypeChars
323 parse arg chars
324 call Process_Keys( chars)
325
326; ---------------------------------------------------------------------------
327; This takes ascii values of one or multiple chars. Multiple chars can be
328; separated by '\'. An leading '\' is optional.
329; Example: TypeAscChars \0\170 gives a null char followed by a not char.
330defc TypeAscChars, TypeEscapedChars
331 Rest = strip( arg( 1))
332 Chars = ''
333 do while Rest <> ''
334 if leftstr( Rest, 1) <> '\' then
335 Rest = '\'Rest
336 endif
337 parse value Rest with '\'Num'\'Rest
338 Num = strip( Num)
339 Rest = strip( Rest)
340
341 if IsNum( Num) and Num < 256 then
342 Chars = Chars''chr( Num)
343 else
344 -- Maybe give an error msg here or ignore this one
345 Chars = Chars''Num
346 endif
347 enddo
348 call Process_Keys( Chars)
349
350; ---------------------------------------------------------------------------
351; executekey can only execute single WM_CHAR keys, either chars or virtual
352; keys defined in the ETK. For multiple keys, keyin can be used.
353defc DoKey, ExecuteKey
354 'Key '1 arg( 1)
355
356; ---------------------------------------------------------------------------
357; Syntax: Key <loopnum> <keystring>
358; In EPM we don't do a getkey() to ask you for the key. You must supply it
359; as part of the command, as in 'key 80 ='.
360defc Key, LoopKey
361 do once = 1 to 1
362 parse value arg( 1) with LoopNum k .
363 if not upcase( LoopNum) = 'RC' then
364 if not IsNum( LoopNum) then
365 sayerror INVALID_NUMBER__MSG
366 leave
367 endif
368 endif
369 fSingleKey = IsSingleKey( k)
370
371 -- jbl: Allow the user to specify the key in the command, so he can
372 -- say 'key 80 =' and avoid the prompt.
373 if k == '' then
374 -- Please specify the key to repeat, as in
375 'SayError' KEY_PROMPT2__MSG '"Key 'loopnum' =", "Key 'loopnum' S+F3".'
376 leave
377 endif
378
379 call NextCmdAltersText()
380 i = 0
381 do forever
382 i = i + 1
383 if IsNum( LoopNum) then
384 if i > LoopNum then
385 leave
386 endif
387 endif
388
389 -- Execute key
390 if fSingleKey then
391 -- Type char
392 executekey k
393 else
394 KeyString = NormalizeKeyString( k)
395 Cmd = GetKeysAVar( 'keydef.'KeyString)
396 if Cmd <> '' then
397 -- Execute Cmd
398 Cmd
399 else
400 -- Execute virtual WM_CHAR key (not used anymore in NEPMD)
401 executekey Resolve_Key( k)
402 endif
403 endif
404
405 if upcase( LoopNum) = 'RC' then
406 if rc then
407 leave
408 endif
409 endif
410
411 enddo
412 enddo
413
414; ---------------------------------------------------------------------------
415defc Keyin
416 parse arg chars
417 --'SayError chars = "'chars'"'
418 if chars == '' then
419 keyin ' '
420 else
421 keyin chars
422 endif
423
424; ---------------------------------------------------------------------------
425; In E3 and EOS2, we can use a_X to enter the value of any key. In EPM,
426; we can't, so the following routine is used by KEY and LOOPKEY to convert
427; from an ASCII key name to the internal value. It handles shift or alt +
428; any letter, or a function key (optionally, with any shift prefix). LAM
429
430; suffix for virtual keys
431; hex dec
432; 02 2 without prefix
433; 0a 10 Sh
434; 12 18 Ctrl
435; 22 34 Alt
436;
437; suffix for letters
438; hex dec
439; 10 16 Ctrl
440; 20 32 Alt
441;
442defproc Resolve_Key( k)
443 kl = lowcase( k)
444 suffix = \2 -- For unshifted function keys
445 if length( k) >= 3 & pos( substr( k, 2, 1), '_-+') then
446 if length( k) > 3 then
447 if substr( kl, 3, 1) = 'f' then -- Shifted function key
448 suffix = substr( \10\34\18, pos( leftstr( kl, 1), 'sac'), 1) -- Set suffix,
449 kl = substr( kl, 3) -- strip shift prefix, and more later...
450 elseif wordpos( substr( kl, 3), 'left up right down') then
451 suffix = substr( \10\34\18, pos( leftstr( kl, 1), 'sac'), 1) -- Set suffix,
452 kl = substr( kl, 3) -- strip shift prefix, and more later...
453 else -- Something we don't handle...
454 'SayError Resolve_key:' sayerrortext(-328)
455 rc = -328
456 endif
457 else -- alt+letter or ctrl+letter
458 k = substr( kl, 3, 1) || substr( \32\16, pos( leftstr( kl, 1), 'ac'), 1)
459 endif
460 endif
461 if leftstr( kl, 1) = 'f' & isnum( substr( kl, 2)) then
462 k = chr( substr( kl, 2) + 31) || suffix
463 elseif wordpos( kl, 'left up right down') then
464 k = chr( wordpos( kl, 'left up right down') + 20) || suffix
465 endif
466 return k
467
468; ---------------------------------------------------------------------------
469; An accelerator key issues a WM_COMMAND message, which is processed by the
470; ProcessCommand command defined in menu.e.
471; Some other defs where accelerator keys are filtered are:
472; def otherkeys, defproc process_key, defc ProcessOtherKeys
473; queryaccelstring returns the command connected with the specified menu item
474; or accelerator key def.
475
476; ---------------------------------------------------------------------------
477; Add or redefine an entry to the active named accelerator key table.
478;
479; Syntax: DefKey( KeyString, Cmd[, 'L'])
480;
481; KeyString prefixes are separated by '_', '+' or '-'. The following
482; prefixes are defined:
483; 'c_' Ctrl
484; 's_' Shift
485; 'a_' Alt
486; In this definition the order of the prefixes doesn't matter, while
487; on execution, the KeyString prefixes are used in the above order.
488; Cmd must be an E command string, not E code.
489; 'L' is the option for defining the key as a lonekey
490; (a lonekey is executed once on releasing the key)
491;
492; Examples:
493; DefKey( 'c_s_Q', 'SayError Ctrl+Shift+Q pressed')
494; DefKey( 'c+s+q', 'SayError Ctrl+Shift+Q pressed') (equivalent)
495; DefKey( 'C-S-q', 'SayError Ctrl+Shift+Q pressed') (equivalent)
496; DefKey( 'altgraf', 'SayError AltGraf key pressed', 'L')
497; For defining non-ASCII keys that don't match the upcase or lowcase
498; procedure processing, the key has to be defined in the correct
499; case:
500; DefKey( '„', 'SayError Lowercase „ (a-umlaut) pressed')
501; DefKey( 's_Ž', 'SayError Uppercase „ (a-umlaut) pressed')
502;
503; For standard accel table defs, the first def wins. This command changes it,
504; so that an accel table can be extended as expected: An already existing
505; accel table entry is overridden by a new one. That makes the last def win
506; and avoids multiple defs for a key.
507;
508defproc DefKey( KeyString, Cmd)
509 universal activeaccel
510 universal lastkeyaccelid
511 universal cua_menu_accel
512 Flags = 0
513
514 String = KeyString
515 call GetAFFlags( String, KeyString, Char, Flags) -- parses modifier prefixes of String
516
517 -- Parse lonekey option
518 fPadKey = 0
519 Options = upcase( arg( 3))
520 if Options <> '' then
521 if pos( Options, 'L') > 0 then
522 Flags = Flags + AF_LONEKEY
523 endif
524 endif
525
526 -- Handle deactivated 'block Alt+letter keys from jumping to menu bar'
527 -- Note: These keys and F10 can't be recorded, they are handled by PM.
528 -- There exists no ETK procs to activate the menu.
529 if IsSingleKey( Char) then
530 if cua_menu_accel then
531 if Flags = AF_ALT & wordpos( Char, upcase( GetMenuAVar( 'usedmenuaccelerators'))) then
532 return
533 endif
534 endif
535 endif
536
537 -- Remove previous key def in array vars, if any
538 PrevCmd = GetKeysAVar('keydef.'KeyString)
539 DelKeysAVar( 'keycmd.'PrevCmd, KeyString)
540
541 -- Save key def in array to allow for searching for KeyString and Cmd
542 SetKeysAVar( 'keydef.'KeyString, Cmd)
543 AddKeysAVar( 'keycmd.'Cmd, KeyString) -- may have multiple key defs
544
545 -- Add KeyString to category array vars
546 SaveKeyCat( KeyString)
547
548 -- Handle key defs that have to be defined as ETK keys instead of PM
549 -- accelerator keys.
550 -- In order to type the single accent key '^' which is created by
551 -- <hat_key>+<space>, space must not be defined as accel key. Therefore
552 -- Space is defined with ExecKeyCmd. That means that it executes the
553 -- command that is stored by DefKey( Space, cmd) as an array var.
554 -- Ignore Alt+keypad number keys as accel keys here. Just save key in
555 -- array to query it by ExecKeyCmd.
556 -- That makes the Alt+keypad number keys work for entering a char by its
557 -- key code.
558 NonAccelKeys = GetKeysAVar( 'nonaccelkeys')
559 if wordpos( KeyString, NonAccelKeys) then
560 -- Save key def in a keyset-specific array
561 SetKeysAVar( 'nonaccelkeydef.'activeaccel'.'KeyString, Cmd)
562 return
563 endif
564
565 if IsSingleKey( Char) then
566 Flags = Flags + AF_CHAR
567 if Flags bitand AF_SHIFT then
568 Key = asc( upcase( Char))
569 else
570 Key = asc( lowcase( Char))
571 endif
572 else
573 VK = GetVKConst( Char)
574 if VK > 0 then
575 Key = VK
576 Flags = Flags + AF_VIRTUALKEY
577 else
578 'SayError Error: Unknown key string 'KeyString' specified.'
579 --dprintf( 'KeyString = 'KeyString', Cmd = 'Cmd', Flags = 'Flags', Key = 'Key', last id = 'lastkeyaccelid)
580 return
581 endif
582 endif
583
584 AccelId = GetKeysAVar( 'keyid.'KeyString)
585 if AccelId = '' then
586 lastkeyaccelid = lastkeyaccelid + 1
587 if lastkeyaccelid = 8101 then -- 8101 is hardcoded as 'configdlg SYS'
588 lastkeyaccelid = lastkeyaccelid + 1
589 endif
590 AccelId = lastkeyaccelid
591 endif
592 -- Avoid to define c_break as accelerator key to keep the internal
593 -- definition working. That key is additionally defined as ProcessBreak
594 -- in STDKEYS.E, to make MenuAccelString() work.
595 if KeyString <> 'c_break' then
596 buildacceltable activeaccel, KeyString''\1''Cmd, Flags, Key, AccelId
597 endif
598
599 -- Save key def in array to allow for searching for KeyString and Cmd
600 SetKeysAVar( 'keyid.'KeyString, AccelId)
601
602 --if KeyString = 'alt' then
603 -- dprintf( 'KeyString = 'KeyString', Cmd = 'Cmd', Flags = 'Flags', Key = 'Key', id = 'lastkeyaccelid)
604 --endif
605 --if KeyString = 'c_s' then
606 -- dprintf( 'KeyString = 'KeyString', Cmd = 'Cmd', Flags = 'Flags', Key = 'Key', this id = 'AccelId', last id = 'lastkeyaccelid)
607 --endif
608
609/*
610 -- For non-letter chars: define also the shifted variant automatically
611 -- to make the defs more keyboard-independible.
612 if Flags bitand AF_CHAR and not Flags bitand AF_SHIFT then
613 if upcase( Key) = lowcase( Key) then
614 Flags = Flags + AF_SHIFT
615 lastkeyaccelid = lastkeyaccelid + 1
616 buildacceltable activeaccel, KeyString''\1''Cmd, Flags, Key, AccelId
617 endif
618 endif
619*/
620
621 return
622
623; Define a cmd to call the proc in profile.erx or for testing
624defc DefKey
625 parse arg KeyString Cmd
626 if upcase( lastword( Cmd)) = 'L' then
627 Options = 'L'
628 Cmd = subword( Cmd, 1, words( Cmd) - 1)
629 else
630 Options = ''
631 endif
632 call DefKey( KeyString, Cmd, Options)
633
634; ---------------------------------------------------------------------------
635; Syntax: UnDefKey( KeyString)
636defproc UnDefKey( KeyString)
637 universal activeaccel
638
639 AccelId = GetKeysAVar( 'keyid.'KeyString)
640 if AccelId <> '' then
641 -- Define Ctrl+Alt (= nothing) for this id
642 -- Don't change the array var to allow for redefining this id again
643 buildacceltable activeaccel, '', AF_CONTROL+AF_VIRTUALKEY, VK_ALT, AccelId
644 -- Remove KeyString from 'keycmd.' array var
645 Cmd = GetKeysAVar('keydef.'KeyString)
646 DelKeysAVar( 'keycmd.'Cmd, KeyString)
647 else
648 -- No error message if key was not defined before
649 endif
650
651 -- Remove KeyString from category array vars
652 DelKeyCat( KeyString)
653
654 return
655
656; Define a cmd to call the proc in profile.erx or for testing
657defc UnDefKey
658 parse arg KeyString
659 call UnDefKey( KeyString)
660
661; ---------------------------------------------------------------------------
662defproc DefKeyCategory( CategoryName)
663 universal activeaccel
664
665 do once = 1 to 1
666 if CategoryName = '' then
667 leave
668 endif
669 Keyset = activeaccel
670 if Keyset = '' then
671 leave
672 endif
673
674 --LastNum = GetKeysAVar( 'keycatname.0')
675 LastNum = GetKeysAVar( 'keycatname.'Keyset'.0')
676 if LastNum = '' then
677 LastNum = 0
678 endif
679
680 -- Add only new categories for keyset
681 fLeave = 0
682 do n = 1 to LastNum
683 KeyCat = GetKeysAVar( 'keycatname.'Keyset'.'n)
684 if CategoryName = KeyCat then
685 -- Don't add existing categories
686 fLeave = 1
687 leave
688 endif
689 enddo
690 if fLeave then
691 leave
692 endif
693
694 LastNum = LastNum + 1
695 --dprintf( 'Keyset = 'Keyset', n = 'LastNum', Category = 'CategoryName)
696 SetKeysAVar( 'keycatname.'Keyset'.'LastNum, CategoryName)
697 SetKeysAVar( 'keycatname.'Keyset'.0', LastNum)
698 enddo
699
700 -- Allow for reset CategoryName if empty
701 SetKeysAVar( 'curkeycatname', CategoryName)
702
703 return
704
705; ---------------------------------------------------------------------------
706; Add KeyString to category array vars
707defproc SaveKeyCat( KeyString)
708 -- Query current key category
709 KeyCat = GetKeysAVar( 'curkeycatname')
710 if KeyCat = '' then
711 KeyCat = 'Miscellaneous'
712 endif
713 Keyset = GetKeysAVar( 'curkeysetcmd')
714 if Keyset <> '' then
715 -- Query previous category array var for KeyString
716 PrevKeyCat = GetKeysAVar( 'keycat.'Keyset'.'KeyString)
717 -- Process only, if change required
718 if PrevKeyCat <> KeyCat then
719 -- Remove KeyString from previous category list
720 DelKeysAVar( 'catkeys.'Keyset'.'PrevKeyCat, KeyString)
721 -- Add KeyString to category list
722 AddKeysAVar( 'catkeys.'Keyset'.'KeyCat, KeyString)
723 -- Save key def in array to allow for searching for KeyString and KeyCat
724 SetKeysAVar( 'keycat.'Keyset'.'KeyString, KeyCat)
725 endif
726 endif
727 return
728
729; ---------------------------------------------------------------------------
730; Remove KeyString from category array vars
731defproc DelKeyCat( KeyString)
732 Keyset = GetKeysAVar( 'curkeysetcmd')
733 if Keyset <> '' then
734 -- Query previous category array var for KeyString
735 PrevKeyCat = GetKeysAVar( 'keycat.'Keyset'.'KeyString)
736 -- Remove KeyString from previous category list
737 DelKeysAVar( 'catkeys.'Keyset'.'PrevKeyCat, KeyString)
738 -- Remove var name from array
739 DropKeysAVar( 'keycat.'Keyset'.'KeyString)
740 endif
741 return
742
743; ---------------------------------------------------------------------------
744defproc GetAFFlags( String, var KeyString, var Char, var Flags)
745 TmpStr = String
746
747 -- Get prefix
748 fC_Prefix = 0
749 fA_Prefix = 0
750 fS_Prefix = 0
751 do l = 1 to length( TmpStr) -- Just an upper limit to prevent looping forever
752 if length( TmpStr) <= 2 then
753 leave
754 endif
755 ch1 = upcase( leftstr( TmpStr, 1))
756 ch2 = substr( TmpStr, 2, 1)
757 p1 = pos( ch1, 'CAS')
758 if not p1 then
759 leave
760 endif
761 p2 = pos( ch2, '_-+')
762 if not p2 then
763 leave
764 endif
765
766 TmpStr = substr( TmpStr, 3)
767 if p1 = 1 then
768 fC_Prefix = 1
769 elseif p1 = 2 then
770 fA_Prefix = 1
771 elseif p1 = 3 then
772 fS_Prefix = 1
773 endif
774 enddo
775
776 -- Char is String without prefix
777 Char = TmpStr
778
779 Flags = 0
780 PrefixString = ''
781 if fC_Prefix = 1 then
782 Flags = Flags + AF_CONTROL -- 16
783 PrefixString = PrefixString'c_'
784 endif
785 if fA_Prefix = 1 then
786 Flags = Flags + AF_ALT -- 32
787 PrefixString = PrefixString'a_'
788 endif
789 if fS_Prefix = 1 then
790 Flags = Flags + AF_SHIFT -- 8
791 PrefixString = PrefixString's_'
792 endif
793
794 -- Try to resolve virtual keys
795 VK = GetVKName( Char)
796
797 -- Build return string
798 if VK = '' then
799 -- If not defined as virtual key, change KeyString to lowercase.
800 -- This allows to use these procs for mouse definitions as well.
801 KeyString = PrefixString''lowcase( Char)
802 else
803 KeyString = PrefixString''VK
804 endif
805
806 return
807
808; ---------------------------------------------------------------------------
809defproc NormalizeKeyString( String)
810 KeyString = ''
811 call GetAFFlags( String, KeyString, Char, Flags)
812 --dprintf( 'NormalizeKeyString( 'arg( 1)'): GetAFFlags( 'String', 'KeyString', 'Char', 'Flags')')
813 return KeyString
814
815; ---------------------------------------------------------------------------
816defproc GetVKConst( String)
817 VK = 0
818 String = upcase( String)
819 if String = 'BREAK' then VK = VK_BREAK
820 elseif String = 'BACKSPACE' then VK = VK_BACKSPACE
821 elseif String = 'BKSPC' then VK = VK_BACKSPACE
822 elseif String = 'TAB' then VK = VK_TAB
823 elseif String = 'BACKTAB' then VK = VK_BACKTAB
824 elseif String = 'NEWLINE' then VK = VK_NEWLINE -- This is the regular Enter key
825 elseif String = 'SHIFT' then VK = VK_SHIFT
826 elseif String = 'CTRL' then VK = VK_CTRL
827 elseif String = 'ALT' then VK = VK_ALT
828 elseif String = 'ALTGRAF' then VK = VK_ALTGRAF
829 elseif String = 'ALTGR' then VK = VK_ALTGRAF
830 elseif String = 'PAUSE' then VK = VK_PAUSE
831 elseif String = 'CAPSLOCK' then VK = VK_CAPSLOCK
832 elseif String = 'ESC' then VK = VK_ESC
833 elseif String = 'SPACE' then VK = VK_SPACE
834 elseif String = 'PAGEUP' then VK = VK_PAGEUP
835 elseif String = 'PGUP' then VK = VK_PAGEUP
836 elseif String = 'PAGEDOWN' then VK = VK_PAGEDOWN
837 elseif String = 'PGDOWN' then VK = VK_PAGEDOWN
838 elseif String = 'PGDN' then VK = VK_PAGEDOWN
839 elseif String = 'END' then VK = VK_END
840 elseif String = 'HOME' then VK = VK_HOME
841 elseif String = 'LEFT' then VK = VK_LEFT
842 elseif String = 'UP' then VK = VK_UP
843 elseif String = 'RIGHT' then VK = VK_RIGHT
844 elseif String = 'DOWN' then VK = VK_DOWN
845 elseif String = 'DN' then VK = VK_DOWN
846 elseif String = 'PRINTSCRN' then VK = VK_PRINTSCRN
847 elseif String = 'INSERT' then VK = VK_INSERT
848 elseif String = 'INS' then VK = VK_INSERT
849 elseif String = 'DELETE' then VK = VK_DELETE
850 elseif String = 'DEL' then VK = VK_DELETE
851 elseif String = 'SCRLLOCK' then VK = VK_SCRLLOCK
852 elseif String = 'NUMLOCK' then VK = VK_NUMLOCK
853 elseif String = 'ENTER' then VK = VK_ENTER -- This is the numeric keypad Enter key
854 elseif String = 'PADENTER' then VK = VK_ENTER -- This is the numeric keypad Enter key
855 elseif String = 'SYSRQ' then VK = VK_SYSRQ
856 elseif String = 'F1' then VK = VK_F1
857 elseif String = 'F2' then VK = VK_F2
858 elseif String = 'F3' then VK = VK_F3
859 elseif String = 'F4' then VK = VK_F4
860 elseif String = 'F5' then VK = VK_F5
861 elseif String = 'F6' then VK = VK_F6
862 elseif String = 'F7' then VK = VK_F7
863 elseif String = 'F8' then VK = VK_F8
864 elseif String = 'F9' then VK = VK_F9
865 elseif String = 'F10' then VK = VK_F10
866 elseif String = 'F11' then VK = VK_F11
867 elseif String = 'F12' then VK = VK_F12
868 endif
869 return VK
870
871; ---------------------------------------------------------------------------
872defproc GetVKName( String)
873 VK = ''
874 String = upcase( String)
875 if String = 'BREAK' then VK = 'break'
876 elseif String = 'BACKSPACE' then VK = 'backspace'
877 elseif String = 'BKSPC' then VK = 'backspace'
878 elseif String = 'TAB' then VK = 'tab'
879 elseif String = 'BACKTAB' then VK = 'backtab'
880 elseif String = 'NEWLINE' then VK = 'newline' -- This is the regular Enter key
881 elseif String = 'SHIFT' then VK = 'shift'
882 elseif String = 'CTRL' then VK = 'ctrl'
883 elseif String = 'ALT' then VK = 'alt'
884 elseif String = 'ALTGRAF' then VK = 'altgraf'
885 elseif String = 'ALTGR' then VK = 'altgraf'
886 elseif String = 'PAUSE' then VK = 'pause'
887 elseif String = 'CAPSLOCK' then VK = 'capslock'
888 elseif String = 'ESC' then VK = 'esc'
889 elseif String = 'SPACE' then VK = 'space'
890 elseif String = 'PAGEUP' then VK = 'pageup'
891 elseif String = 'PGUP' then VK = 'pageup'
892 elseif String = 'PAGEDOWN' then VK = 'pagedown'
893 elseif String = 'PGDOWN' then VK = 'pagedown'
894 elseif String = 'PGDN' then VK = 'pagedown'
895 elseif String = 'END' then VK = 'end'
896 elseif String = 'HOME' then VK = 'home'
897 elseif String = 'LEFT' then VK = 'left'
898 elseif String = 'UP' then VK = 'up'
899 elseif String = 'RIGHT' then VK = 'right'
900 elseif String = 'DOWN' then VK = 'down'
901 elseif String = 'DN' then VK = 'down'
902 elseif String = 'PRINTSCRN' then VK = 'printscrn'
903 elseif String = 'INSERT' then VK = 'insert'
904 elseif String = 'INS' then VK = 'insert'
905 elseif String = 'DELETE' then VK = 'delete'
906 elseif String = 'DEL' then VK = 'delete'
907 elseif String = 'SCRLLOCK' then VK = 'scrllock'
908 elseif String = 'NUMLOCK' then VK = 'numlock'
909 elseif String = 'ENTER' then VK = 'enter' -- This is the numeric keypad Enter key
910 elseif String = 'PADENTER' then VK = 'enter' -- This is the numeric keypad Enter key
911 elseif String = 'SYSRQ' then VK = 'sysrq'
912 elseif String = 'F1' then VK = 'f1'
913 elseif String = 'F2' then VK = 'f2'
914 elseif String = 'F3' then VK = 'f3'
915 elseif String = 'F4' then VK = 'f4'
916 elseif String = 'F5' then VK = 'f5'
917 elseif String = 'F6' then VK = 'f6'
918 elseif String = 'F7' then VK = 'f7'
919 elseif String = 'F8' then VK = 'f8'
920 elseif String = 'F9' then VK = 'f9'
921 elseif String = 'F10' then VK = 'f10'
922 elseif String = 'F11' then VK = 'f11'
923 elseif String = 'F12' then VK = 'f12'
924 endif
925 return VK
926
927; ---------------------------------------------------------------------------
928const
929; Also added to ENGLISH.E
930compile if not defined( NEWLINE_KEY__MSG)
931 NEWLINE_KEY__MSG = 'Newline'
932compile endif
933
934defproc GetVKMenuName( String)
935 VK = ''
936 String = upcase( String)
937 if String = 'BREAK' then VK = 'Brk'
938 elseif String = 'BACKSPACE' then VK = BACKSPACE_KEY__MSG
939 elseif String = 'BKSPC' then VK = BACKSPACE_KEY__MSG
940 elseif String = 'TAB' then VK = 'Tab'
941 elseif String = 'BACKTAB' then VK = 'BackTab'
942 elseif String = 'NEWLINE' then VK = NEWLINE_KEY__MSG -- This is the regular Enter key
943 elseif String = 'SHIFT' then VK = SHIFT_KEY__MSG
944 elseif String = 'CTRL' then VK = CTRL_KEY__MSG
945 elseif String = 'ALT' then VK = ALT_KEY__MSG
946 elseif String = 'ALTGRAF' then VK = 'AltGraf'
947 elseif String = 'ALTGR' then VK = 'AltGraf'
948 elseif String = 'PAUSE' then VK = 'Pause'
949 elseif String = 'CAPSLOCK' then VK = 'Capslock'
950 elseif String = 'ESC' then VK = ESCAPE_KEY__MSG
951 elseif String = 'SPACE' then VK = 'Space'
952 elseif String = 'PAGEUP' then VK = 'PgUp'
953 elseif String = 'PGUP' then VK = 'PgUp'
954 elseif String = 'PAGEDOWN' then VK = 'PgDown'
955 elseif String = 'PGDOWN' then VK = 'PgDown'
956 elseif String = 'PGDN' then VK = 'PgDown'
957 elseif String = 'END' then VK = 'End'
958 elseif String = 'HOME' then VK = 'Home'
959 elseif String = 'LEFT' then VK = 'Left'
960 elseif String = 'UP' then VK = UP_KEY__MSG
961 elseif String = 'RIGHT' then VK = 'Right'
962 elseif String = 'DOWN' then VK = DOWN_KEY__MSG
963 elseif String = 'DN' then VK = DOWN_KEY__MSG
964 elseif String = 'PRINTSCRN' then VK = 'PrtScrn'
965 elseif String = 'INSERT' then VK = INSERT_KEY__MSG
966 elseif String = 'INS' then VK = INSERT_KEY__MSG
967 elseif String = 'DELETE' then VK = DELETE_KEY__MSG
968 elseif String = 'DEL' then VK = DELETE_KEY__MSG
969 elseif String = 'SCRLLOCK' then VK = 'ScrlLock'
970 elseif String = 'NUMLOCK' then VK = 'NumLock'
971 elseif String = 'ENTER' then VK = PADENTER_KEY__MSG -- This is the numeric keypad Enter key
972 elseif String = 'PADENTER' then VK = PADENTER_KEY__MSG -- This is the numeric keypad Enter key
973 elseif String = 'SYSRQ' then VK = 'SysRq'
974 elseif String = 'F1' then VK = 'F1'
975 elseif String = 'F2' then VK = 'F2'
976 elseif String = 'F3' then VK = 'F3'
977 elseif String = 'F4' then VK = 'F4'
978 elseif String = 'F5' then VK = 'F5'
979 elseif String = 'F6' then VK = 'F6'
980 elseif String = 'F7' then VK = 'F7'
981 elseif String = 'F8' then VK = 'F8'
982 elseif String = 'F9' then VK = 'F9'
983 elseif String = 'F10' then VK = 'F10'
984 elseif String = 'F11' then VK = 'F11'
985 elseif String = 'F12' then VK = 'F12'
986 endif
987 return VK
988
989; ---------------------------------------------------------------------------
990defproc GetVKString( VkCode)
991 String = ''
992 if VkCode = VK_BREAK then String = 'break'
993 elseif VkCode = VK_BACKSPACE then String = 'backspace'
994 elseif VkCode = VK_TAB then String = 'tab'
995 elseif VkCode = VK_BACKTAB then String = 'backtab'
996 elseif VkCode = VK_NEWLINE then String = 'newline'
997 elseif VkCode = VK_SHIFT then String = 'shift'
998 elseif VkCode = VK_CTRL then String = 'ctrl'
999 elseif VkCode = VK_ALT then String = 'alt'
1000 elseif VkCode = VK_ALTGRAF then String = 'altgraf'
1001 elseif VkCode = VK_PAUSE then String = 'pause'
1002 elseif VkCode = VK_CAPSLOCK then String = 'capslock'
1003 elseif VkCode = VK_ESC then String = 'esc'
1004 elseif VkCode = VK_SPACE then String = 'space'
1005 elseif VkCode = VK_PAGEUP then String = 'pageup'
1006 elseif VkCode = VK_PAGEDOWN then String = 'pagedown'
1007 elseif VkCode = VK_END then String = 'end'
1008 elseif VkCode = VK_HOME then String = 'home'
1009 elseif VkCode = VK_LEFT then String = 'left'
1010 elseif VkCode = VK_UP then String = 'up'
1011 elseif VkCode = VK_RIGHT then String = 'right'
1012 elseif VkCode = VK_DOWN then String = 'down'
1013 elseif VkCode = VK_DOWN then String = 'dn'
1014 elseif VkCode = VK_PRINTSCRN then String = 'printscrn'
1015 elseif VkCode = VK_INSERT then String = 'insert'
1016 elseif VkCode = VK_DELETE then String = 'delete'
1017 elseif VkCode = VK_SCRLLOCK then String = 'scrllock'
1018 elseif VkCode = VK_NUMLOCK then String = 'numlock'
1019 elseif VkCode = VK_ENTER then String = 'padenter'
1020 elseif VkCode = VK_SYSRQ then String = 'sysrq'
1021 elseif VkCode = VK_F1 then String = 'f1'
1022 elseif VkCode = VK_F2 then String = 'f2'
1023 elseif VkCode = VK_F3 then String = 'f3'
1024 elseif VkCode = VK_F4 then String = 'f4'
1025 elseif VkCode = VK_F5 then String = 'f5'
1026 elseif VkCode = VK_F6 then String = 'f6'
1027 elseif VkCode = VK_F7 then String = 'f7'
1028 elseif VkCode = VK_F8 then String = 'f8'
1029 elseif VkCode = VK_F9 then String = 'f9'
1030 elseif VkCode = VK_F10 then String = 'f10'
1031 elseif VkCode = VK_F11 then String = 'f11'
1032 elseif VkCode = VK_F12 then String = 'f12'
1033 endif
1034 return String
1035
1036; ---------------------------------------------------------------------------
1037; Get key def as appendix for a menu item text, with a prepended tab char,
1038; if any text. Supports multiple Cmds, if specified as separate args.
1039defproc MenuAccelString
1040 AccelString = ''
1041 do i = 1 to arg()
1042 Cmd = arg( i)
1043 if Cmd = '' then
1044 iterate
1045 endif
1046
1047 -- Query array var, defined by DefKey
1048 KeyString = strip( GetKeysAVar( 'keycmd.'Cmd))
1049 if KeyString = '' then
1050 iterate
1051 endif
1052
1053 -- A Cmd may have multiple key defs, each appended by a space
1054 do w = 1 to words( KeyString)
1055 Rest = word( KeyString, w)
1056 ThisString = ''
1057 if pos( 'c_', Rest) = 1 then
1058 ThisString = ThisString''CTRL_KEY__MSG'+'
1059 Rest = substr( Rest, 3)
1060 endif
1061 if pos( 'a_', Rest) = 1 then
1062 ThisString = ThisString''ALT_KEY__MSG'+'
1063 Rest = substr( Rest, 3)
1064 endif
1065 if pos( 's_', Rest) = 1 then
1066 ThisString = ThisString''SHIFT_KEY__MSG'+'
1067 Rest = substr( Rest, 3)
1068 endif
1069 if Rest <> '' then
1070 VKString = GetVKMenuName( Rest)
1071 if VKString <> '' then
1072 ThisString = ThisString''VKString
1073 else
1074 ThisString = ThisString''upcase( Rest)
1075 endif
1076 endif
1077 if AccelString <> '' then
1078 AccelString = AccelString' | 'ThisString
1079 else
1080 AccelString = ThisString
1081 endif
1082 enddo
1083 enddo
1084 if AccelString <> '' then
1085 AccelString = \9''AccelString
1086 endif
1087 return AccelString
1088
1089; For testing:
1090defc MenuAccelString
1091 Cmd = strip( arg( 1))
1092 'SayError Menu item text appendix for "'Cmd'" is: |'MenuAccelString( Cmd)'|'
1093
1094; ---------------------------------------------------------------------------
1095; This is for .KEYSET_DEFINITIONS_* files. It converts a KeyString to a
1096; String as used for menu item texts to display the key def.
1097defproc ConvertKeyString( KeyString)
1098 ThisString = ''
1099 Rest = KeyString
1100 do while Rest <> ''
1101 if pos( 'c_', Rest) = 1 then
1102 ThisString = ThisString''CTRL_KEY__MSG'+'
1103 Rest = substr( Rest, 3)
1104 iterate
1105 endif
1106 if pos( 'a_', Rest) = 1 then
1107 ThisString = ThisString''ALT_KEY__MSG'+'
1108 Rest = substr( Rest, 3)
1109 iterate
1110 endif
1111 if pos( 's_', Rest) = 1 then
1112 ThisString = ThisString''SHIFT_KEY__MSG'+'
1113 Rest = substr( Rest, 3)
1114 iterate
1115 endif
1116 if Rest <> '' then
1117 VKString = GetVKMenuName( Rest)
1118 if VKString <> '' then
1119 ThisString = ThisString''VKString
1120 else
1121 CapRest = upcase( leftstr( Rest, 1))''substr( Rest, 2)
1122 ThisString = ThisString''CapRest
1123 endif
1124 Rest = ''
1125 endif
1126 enddo
1127
1128 return ThisString
1129
1130; ---------------------------------------------------------------------------
1131; Called by ProcessCommand in MENU.E
1132defproc ExecAccelKey
1133 parse value( arg( 1)) with KeyString \1 Cmd
1134
1135 call SaveKeyCmd( arg( 1))
1136 fExpanded = ExpandKey()
1137 --dprintf( 'ExecAccelKey: KeyString = 'KeyString', fExpanded = 'fExpanded)
1138
1139 if fExpanded = 0 then
1140 Cmd
1141 endif
1142 return
1143
1144; ---------------------------------------------------------------------------
1145; ExpandKey is called by ExecKeyCmd, ExecAccelKey and ExecMenuItem.
1146defproc ExpandKey
1147 universal expand_on
1148
1149 fExpanded = 0
1150 do once = 1 to 1
1151
1152 -- Check first if any expansion is enabled
1153 KeyPath = '\NEPMD\User\SpecialKeys\MatchFindOpening'
1154 fFindOpening = QueryConfigKey( KeyPath)
1155 KeyPath = '\NEPMD\User\SpecialKeys\MatchInsertPair'
1156 fInsertPair = QueryConfigKey( KeyPath)
1157
1158 if fFindOpening | fInsertPair | expand_on then
1159 -- Ensure that cursor is not within a literal
1160 Mode = GetMode()
1161 if InsideLiteral( Mode) then
1162 leave
1163 endif
1164 endif
1165
1166 if fFindOpening | fInsertPair then
1167 -- Try to expand match char
1168 fExpanded = (ExpandMatchChars() == 1)
1169 if fExpanded = 1 then
1170 leave
1171 endif
1172 endif
1173
1174 if expand_on then
1175 -- Try to expand syntax
1176 fExpanded = (ExpandSyntax() == 1)
1177 if fExpanded = 1 then
1178 leave
1179 endif
1180 endif
1181 enddo
1182
1183 -- fExpanded = 1 must stop further processing in the calling proc.
1184 return fExpanded
1185
1186; ---------------------------------------------------------------------------
1187; Keyset array vars:
1188;
1189; 'keysets' list of defined keysets
1190; 'keyset.'name list of subkeysets (keyset cmds) for keyset name
1191; 'keysetused.'cmdname list of keysets that use cmdname
1192; (this var allows for changing keysets for all
1193; loaded files, not just for newly loaded files)
1194;
1195; Examples with cuakeys active: Examples without cuakeys active:
1196; 'keysets' = 'std shell' 'keysets' = 'std shell'
1197; 'keyset.std' = 'std cua' 'keyset.std' = 'std'
1198; 'keysetused.std' = 'std shell' 'keysetused.std' = 'std shell'
1199; 'keyset.shell' = 'std cua shell' 'keyset.shell' = 'std shell'
1200; 'keysetused.shell' = 'shell' 'keysetused.shell' = 'shell'
1201;
1202; ---------------------------------------------------------------------------
1203; Define a named accel table. It has to be activated with SetKeyset.
1204;
1205; Syntax: DefKeyset [<name>] [<keyset_cmd_1> <keyset_cmd_2> ...]
1206; DefKeyset [<name>] [<name_3>value] <keyset_cmd_4> ...]
1207;
1208; Instead of a keyset cmd, a keyset name can be specified (with 'value'
1209; appended). Then the specified keyset will be extended.
1210defc DefAccel, DefKeyset
1211 universal activeaccel
1212 universal lastkeyaccelid
1213 universal LoadState
1214
1215 -- Default accel table name = 'std' (standard EPM uses 'defaccel')
1216 StdName = 'std'
1217
1218 -- Init accel table defs
1219 StartAccelId = 10000 -- max. = 65534 (65535 is hardcoded as Halt cmd)
1220 if lastkeyaccelid < StartAccelId then
1221 lastkeyaccelid = StartAccelId
1222 activeaccel = StdName
1223 -- Bug in ETK: first def is ignored, therefore add a dummy def here
1224 -- This must be a valid def, otherwise the menu is not loaded at startup:
1225 buildacceltable StdName, 'SayError Ignored!', AF_VIRTUALKEY, VK_ALT, lastkeyaccelid
1226 endif
1227
1228 parse arg Keyset SubKeysets
1229
1230 Keyset = strip( Keyset)
1231 if Keyset = '' | lowcase( Keyset) = 'edit' | lowcase( Keyset) = 'default' then
1232 Keyset = StdName
1233 endif
1234 Keyset = lowcase( Keyset)
1235
1236 SubKeysets = strip( SubKeysets)
1237 SubKeysets = lowcase( SubKeysets)
1238 if SubKeysets = '' then
1239 -- Use default keyset defs
1240 if Keyset = StdName then
1241 SubKeysets = StdName -- use defc stdkeys
1242 else
1243 SubKeysets = StdName'value' Keyset -- extend stdkeys with defc Namekeys
1244 endif
1245 endif
1246
1247 SavedAccel = activeaccel
1248 activeaccel = Keyset
1249 --dprintf( 'DefKeyset: Keyset = 'Keyset', SubKeysets = 'SubKeysets', SavedAccel = 'SavedAccel)
1250
1251 -- Parse keyset definition list and get resolved list of SubKeysets.
1252 -- Keyset command defs have 'keys' appended. In the following, the
1253 -- term 'keyset cmd' means the command without 'keys'. The same applies
1254 -- for the array vars, were the string without 'keys' is used, too.
1255 List = SubKeysets
1256 SubKeysets = ''
1257 do w = 1 to words( List)
1258 SubKeyset = word( List, w)
1259 --dprintf( 'DefKeyset: SubKeyset = 'SubKeyset)
1260 -- Allow for specifying a keyset name instead of a list of keyset defs
1261 -- (e.g. 'stdvalue' instead of 'std cua')
1262 if rightstr( SubKeyset, 5) = 'value' and length( SubKeyset) > 5 then
1263 SubName = leftstr( SubKeyset, length( SubKeyset) - 5)
1264 SubList = GetKeysAVar( 'keyset.'SubName)
1265 do s = 1 to words( SubList)
1266 ThisSubKeyset = word( SubList, s)
1267 SubKeysets = SubKeysets ThisSubKeyset
1268 enddo
1269 else
1270 SubKeysets = SubKeysets SubKeyset
1271 endif
1272 enddo
1273 SubKeysets = strip( SubKeysets)
1274
1275 -- Remove doubled and undefined entries
1276 -- Try to link SubKeysets if not defined
1277 Next = ''
1278 Rest = SubKeysets
1279 do forever
1280 if Rest = '' then
1281 leave
1282 endif
1283 parse value Rest with SubKeyset Rest
1284 SubKeyset = strip( SubKeyset)
1285 Rest = strip( Rest)
1286 if wordpos( SubKeyset, Rest) then
1287 iterate
1288 endif
1289 -- Check if SubKeyset'keys' is defined as defc and
1290 -- maybe link SubKeyset'keys'
1291 fIsDefined = KeysetCmdExists( SubKeyset)
1292 -- Append SubKeyset only if defined
1293 if not fIsDefined then
1294 iterate
1295 endif
1296 Next = Next SubKeyset
1297 enddo
1298 SubKeysets = strip( Next)
1299
1300 if SubKeysets <> '' then
1301 -- Change array vars for this keyset name
1302 PrevSubKeysets = GetKeysAVar( 'keyset.'Keyset)
1303 --dprintf( 'DefKeySet: PrevSubKeysets = 'PrevSubKeysets)
1304 if PrevSubKeysets <> SubKeysets then
1305 -- For all previous keyset commands
1306 do k = 1 to words( PrevSubKeysets)
1307 SubKeyset = word( PrevSubKeysets, k)
1308 -- Remove keyset name from array var for this SubKeyset
1309 DelKeysAVar( 'keysetused.'SubKeyset, Keyset)
1310 enddo
1311 endif
1312
1313 --dprintf( 'DefKeySet: Keyset = 'Keyset', SubKeysets = 'SubKeysets)
1314
1315 -- Set array vars for this keyset name
1316 AddKeysAVar( 'keysets', Keyset)
1317 SetKeysAVar( 'keyset.'Keyset, SubKeysets)
1318
1319 -- Set array var for each keyset command and execute it
1320 do k = 1 to words( SubKeysets)
1321 SubKeyset = word( SubKeysets, k)
1322 -- Add keyset name to array var for this keyset cmd
1323 AddKeysAVar( 'keysetused.'SubKeyset, Keyset)
1324 -- Execute keyset cmd (with 'keys' appended)
1325 SubKeyset'keys'
1326 enddo
1327
1328 -- For Keyset = 'std' write also AddKeyDefs
1329 if Keyset = 'std' then
1330 AddKeyDefs = word( SubKeysets, 2) -- empty for 'std' = 'std'
1331 KeyPathSelected = '\NEPMD\User\Keysets\AddKeyDefs\Selected'
1332 WriteConfigKey( KeyPathSelected, AddKeyDefs)
1333 endif
1334
1335 endif
1336
1337 -- The BlockAlt key subset needn't to be added to the 'keysets' array var
1338 'BlockAltKeys'
1339
1340 activeaccel = SavedAccel
1341
1342; ---------------------------------------------------------------------------
1343defproc KeysetCmdExists( SubKeyset)
1344 fIsDefined = 0
1345
1346 do once = 1 to 1
1347 -- Check if Keyset cmd exists
1348 if isadefc( SubKeyset'keys') then
1349 fIsDefined = 1
1350 leave
1351 endif
1352
1353 -- Check if .EX file exists
1354 findfile ExFile, SubKeyset'keys.ex', 'EPMPATH'
1355 if rc then
1356 leave
1357 endif
1358
1359 -- Check if .EX file is linked
1360 linkedrc = linked( SubKeyset'keys.ex')
1361 if linkedrc >= 0 then
1362 leave
1363 endif
1364
1365 -- Link .EX file
1366 'Link quiet' SubKeyset'keys'
1367 --dprintf( 'KeysetCmdExists: Keyset "'SubKeyset'Keys" linked, rc = 'rc)
1368
1369 -- Check rc from Link if .EX file is linked
1370 if rc < 0 then
1371 leave
1372 endif
1373
1374 -- Check if Keyset cmd exists
1375 if isadefc( SubKeyset'keys') then
1376 fIsDefined = 1
1377 leave
1378 endif
1379 enddo
1380
1381 return fIsDefined
1382
1383; ---------------------------------------------------------------------------
1384; Block Alt and/or AltGr from switching to the menu
1385; PM defines the key F10 to jump to the menu, like Alt and AltGraf.
1386; It can be used instead, if it's not redefined.
1387; To block these PM def, Alt and AltGraf have to be defined with the
1388; AF_LONEKEY flag.
1389defc BlockAltKeys
1390 -- Block Alt and/or AltGr from switching to the menu
1391 -- PM defines the key F10 to jump to the menu, like Alt and AltGraf.
1392 -- It can be used instead, if it's not redefined.
1393 -- To block these PM def, Alt and AltGraf have to be defined with the
1394 -- AF_LONEKEY flag.
1395 -- Redefine every used accel keyset
1396 KeyPath = '\NEPMD\User\SpecialKeys\Alt\BlockLeftAlt'
1397 fBlocked1 = QueryConfigKey( KeyPath)
1398 KeyPath = '\NEPMD\User\SpecialKeys\Alt\BlockRightAlt'
1399 fBlocked2 = QueryConfigKey( KeyPath)
1400
1401 if fBlocked1 = 1 then
1402 DefKeyCategory( 'Block alt keys')
1403 DefKey( 'alt', '', 'L')
1404 else
1405 UnDefKey( 'alt')
1406 endif
1407
1408 if fBlocked2 = 1 then
1409 DefKeyCategory( 'Block alt keys')
1410 DefKey( 'altgraf', '', 'L')
1411 else
1412 UnDefKey( 'altgraf')
1413 endif
1414
1415; ---------------------------------------------------------------------------
1416; Redefine every used accel keyset. This can be used by the menu commands
1417; toggle_block_left_alt_key and toggle_block_right_alt_key to activate the
1418; changed behavior for all loaded keysets.
1419defc RefreshBlockAlt
1420 universal activeaccel
1421
1422 KeyPath = '\NEPMD\User\SpecialKeys\Alt\BlockLeftAlt'
1423 fBlocked1 = QueryConfigKey( KeyPath)
1424 KeyPath = '\NEPMD\User\SpecialKeys\Alt\BlockRightAlt'
1425 fBlocked2 = QueryConfigKey( KeyPath)
1426
1427 SavedAccel = activeaccel
1428 KeySets = strip( GetKeysAVar( 'keysets'))
1429
1430 do w = 1 to words( KeySets)
1431 KeySet = word( KeySets, w)
1432 activeaccel = KeySet
1433
1434 if fBlocked1 = 1 then
1435 DefKeyCategory( 'Block alt keys')
1436 DefKey( 'alt', '', 'L')
1437 else
1438 UnDefKey( 'alt')
1439 endif
1440
1441 if fBlocked2 = 1 then
1442 DefKeyCategory( 'Block alt keys')
1443 DefKey( 'altgraf', '', 'L')
1444 else
1445 UnDefKey( 'altgraf')
1446 endif
1447
1448 enddo
1449 activeaccel = SavedAccel
1450
1451 activateacceltable activeaccel
1452
1453; ---------------------------------------------------------------------------
1454defc DisableSwitchKeyset
1455 universal switchkeysetdisabled
1456 switchkeysetdisabled = 1
1457
1458defc EnableSwitchKeyset
1459 universal switchkeysetdisabled
1460 switchkeysetdisabled = 0
1461
1462; ---------------------------------------------------------------------------
1463defproc ExpandKeyset
1464 parse arg Keyset SubKeysets
1465 Keyset = lowcase( strip( Keyset))
1466 -- Default accel table name = 'std' (standard EPM uses 'defaccel')
1467 if Keyset = '' | Keyset = 'default' then
1468 Keyset = 'std'
1469 endif
1470 SubKeysets = lowcase( strip( SubKeysets))
1471 if SubKeysets = '' then
1472 SubKeysets = GetKeysAVar( 'keyset.'Keyset)
1473 endif
1474 return strip( Keyset SubKeysets)
1475
1476; ---------------------------------------------------------------------------
1477; Init 'std' keyset. This must be executed before executing LoadAccel and
1478; before loading the menu. It is done in CONFIG.E:"defc InitConfig".
1479defc InitStdKeyset
1480 StdName = 'std'
1481 'SetKeyset2' StdName
1482
1483; ---------------------------------------------------------------------------
1484defc LoadAccel
1485 parse arg Args
1486 if Args = '' then
1487 'SetKeyset std'
1488 else
1489 'SetKeyset' Args -- defined in MODEEXEC.E
1490 endif
1491
1492; ---------------------------------------------------------------------------
1493; SetKeyset: defined in MODEEXEC.E, contains mode-specific part, calls:
1494; SetKeyset2: switches keyset and maybe defines it.
1495; Syntax: SetKeyset <keyset_name> [<list_of_keyset_defs>]
1496; Examples:
1497; SetKeyset std switch to keyset 'std'
1498; SetKeyset std std cua define and switch to keyset 'std' = StdKeys and CuaKeys
1499; SetKeyset std std define and switch to keyset 'std' = StdKeys
1500; SetKeyset rexx stdvalue rexx define and switch to keyset 'rexx' = value of 'std' and RexxKeys
1501; SetKeyset rexx switch to keyset 'rexx'
1502defc SetKeyset2
1503 universal activeaccel
1504 universal switchkeysetdisabled
1505 universal keysetchanged
1506 universal menuloaded
1507 universal refreshmenudisabled
1508 universal refreshmenustate
1509
1510 parse value ExpandKeyset( arg( 1)) with Keyset SubKeysets
1511
1512 DefinedKeysets = GetKeysAVar( 'keysets')
1513 KeyPathSelected = '\NEPMD\User\Keysets\AddKeyDefs\Selected'
1514 AddKeyDefs = QueryConfigKey( KeyPathSelected)
1515 PrevSubKeysets = strip( GetKeysAVar( 'keyset.'Keyset))
1516 --dprintf( 'SetKeyset2: args = 'arg( 1)', PrevSubKeysets = 'PrevSubKeysets', '.filename)
1517
1518 -- Parse keyset definition list and get resolved list of SubKeysets.
1519 -- Keyset command defs have 'keys' appended. In the following, the
1520 -- term 'keyset cmd' means the command without 'keys'. The same applies
1521 -- for the array vars, where the string without 'keys' is used, too.
1522 List = SubKeysets
1523 SubKeysets = ''
1524 do w = 1 to words( List)
1525 SubKeyset = word( List, w)
1526 --dprintf( 'SefKeyset2: SubKeyset = 'SubKeyset)
1527 -- Allow for specifying a keyset name instead of a list of keyset defs
1528 -- (e.g. 'stdvalue' instead of 'std cua')
1529 if rightstr( SubKeyset, 5) = 'value' and length( SubKeyset) > 5 then
1530 SubName = leftstr( SubKeyset, length( SubKeyset) - 5)
1531 SubList = GetKeysAVar( 'keyset.'SubName)
1532 do s = 1 to words( SubList)
1533 ThisSubKeyset = word( SubList, s)
1534 SubKeysets = SubKeysets ThisSubKeyset
1535 enddo
1536 else
1537 SubKeysets = SubKeysets SubKeyset
1538 endif
1539 enddo
1540 SubKeysets = strip( SubKeysets)
1541
1542 if SubKeysets = '' then
1543 -- Switch to keyset only
1544 if PrevSubKeysets = '' then
1545 if Keyset = 'std' then
1546 SubKeysets = strip( Keyset AddKeyDefs)
1547 else
1548 SubKeysets = strip( strip( 'std' AddKeyDefs) Keyset)
1549 endif
1550 else
1551 SubKeysets = PrevSubKeysets
1552 endif
1553 else
1554 -- Define keyset
1555 endif
1556
1557 -- Store current keyset in array var and query LastKeyset
1558 LastKeyset = GetKeysAVar( 'lastkeyset')
1559 call SetKeysAVar( 'lastkeyset', Keyset)
1560
1561 --dprintf( 'SetKeyset2: DefinedKeysets = "'DefinedKeysets'", PrevSubKeysets = "'PrevSubKeysets'", SubKeysets = "'SubKeysets'", Keyset = 'Keyset', activeaccel = 'activeaccel)
1562 if wordpos( Keyset, DefinedKeysets) = 0 | SubKeysets <> PrevSubKeysets then
1563 -- Reset category names and keys first.
1564 -- Store Keyset. It is used for to define keyset-specific categories.
1565 -- See definitions for DefKeyCategory and SaveKeyCat procs above.
1566 SetKeysAVar( 'curkeysetcmd', Keyset)
1567
1568 -- Ensure that category is reset before DefKeyset
1569 DefKeyCategory( '')
1570
1571 -- Define keyset
1572 --dprintf( 'SetKeyset2: Define keyset, "DefKeyset' strip( Keyset SubKeysets)'" executed')
1573 'DefKeyset' strip( Keyset SubKeysets)
1574
1575 -- Ensure that category is reset after DefKeyset
1576 DefKeyCategory( '')
1577 endif
1578
1579 do once = 1 to 1
1580 if switchkeysetdisabled then
1581 leave
1582 endif
1583 --dprintf( 'SetKeyset2: SwitchKeyset' Keyset SubKeysets)
1584 -- Switch to keyset
1585 if Keyset <> LastKeyset | SubKeysets <> PrevSubkeysets then
1586 --dprintf( 'SetKeyset2: SwitchKeyset' Keyset SubKeysets)
1587 'SwitchKeyset' Keyset SubKeysets
1588 endif
1589 enddo
1590
1591 -- This is required to update the menu texts, e.g. key mnemonics
1592 -- RefreshMenu slows file switching down.
1593 do once = 1 to 1
1594 if not menuloaded then
1595 leave
1596 elseif Keyset = LastKeyset & SubKeysets = PrevSubkeysets then
1597 leave
1598 endif
1599 -- 'VSyncCursor' was added because of showwindow to keep scroll position
1600 'VSyncCursor'
1601
1602 if refreshmenudisabled <> 1 then
1603 -- Rebuild menu
1604 -- Suppress refresh of submenus
1605 refreshmenustate = 1
1606 'PostMe RefreshMenu' -- PostMe required to make it run properly
1607 --dprintf( '* RefreshMenu executed')
1608 endif
1609 enddo
1610
1611 -- Execute basic mouse defs, not defined in StdKeys
1612 -- Always required to make the mouse work, even at startup
1613 'Mouse_Init'
1614
1615; ---------------------------------------------------------------------------
1616; This ic executed by SetKeyset2.
1617defc SwitchKeyset
1618 universal activeaccel
1619
1620 PrevKeyset = activeaccel
1621 PrevSubKeysets = GetKeysAVar( 'keyset.'PrevKeyset)
1622
1623 parse value ExpandKeyset( arg( 1)) with Keyset SubKeysets
1624 --dprintf( 'SwitchKeyset: args = 'args', Keyset = 'Keyset', SubKeysets = 'SubKeysets)
1625
1626 -- Activate keyset: accelerator keys
1627 --dprintf( 'SwitchKeyset: activeaccel = 'activeaccel', Keyset = 'Keyset)
1628 activeaccel = Keyset
1629 activateacceltable activeaccel
1630
1631 -- Activate keyset: keyset-specific array defs (for ExecKeyCmd)
1632 NonAccelKeys = GetKeysAVar( 'nonaccelkeys')
1633 do w = 1 to words( NonAccelKeys)
1634 KeyString = word( NonAccelKeys, w)
1635 NonAccelKeyDef = GetKeysAVar( 'nonaccelkeydef.'Keyset'.'KeyString)
1636 SetKeysAVar( 'keydef.'KeyString, NonAccelKeyDef)
1637 enddo
1638
1639 -- Switch to previously defined keyset. Redefine menu accel strings.
1640 do k = 1 to words( SubKeysets)
1641 SubKeyset = word( SubKeysets, k)
1642
1643 -- Execute keyset cmd (with 'keys' appended). This calls a set of DefKey
1644 -- procs.
1645 --dprintf( 'SwitchKeyset: Executing "'SubKeyset'keys" for '.filename)
1646 SubKeyset'keys'
1647 enddo
1648 --dprintf( 'SwitchKeyset: Switch keyset, keyset cmds executed: 'Keyset' = 'SubKeysets)
1649
1650; ---------------------------------------------------------------------------
1651defc ReloadKeyset
1652 universal activeaccel
1653
1654 Keyset = activeaccel
1655 SubKeysets = GetKeysAVar( 'keyset.'Keyset)
1656
1657 'DelKeyset'
1658
1659 -- Reset list of defined keysets to make SetKeyset2 execute DefKeyset
1660 call SetKeysAVar( 'keysets', '')
1661
1662 -- Redef key defs
1663 --dprintf( 'ReloadKeyset: SetKeyset2' Keyset SubKeysets)
1664 'SetKeyset2' Keyset SubKeysets
1665
1666; ---------------------------------------------------------------------------
1667defc ShowKeyset
1668 universal activeaccel
1669
1670 parse arg Keyset
1671 if Keyset = '' then
1672 Keyset = activeaccel
1673 endif
1674
1675 TmpFileName = '.KEYSET_DEFINITIONS_'Keyset
1676 getfileid startfid
1677 display -3
1678 if IsFileLoaded( TmpFileName) then
1679 'xcom e /n' TmpFileName -- activate tmp file
1680 else
1681 'xcom e /c' TmpFileName -- create tmp file
1682 deleteline -- delete first line (EPM automatically creates line 1)
1683 endif
1684 getfileid tmpfid
1685 savedlast = .last
1686 .autosave = 0
1687
1688 insertline copies('-', 78), .last + 1
1689 SubKeysets = GetKeysAVar( 'keyset.'Keyset)
1690 insertline 'Keyset: 'Keyset' - Subkeysets: 'SubKeysets, .last + 1
1691 insertline '', .last + 1
1692
1693 LastNum = GetKeysAVar( 'keycatname.'Keyset'.0')
1694 --dprintf( 'LastNum = 'LastNum)
1695 Indent = copies( ' ', 3)
1696 do n = 1 to LastNum
1697 KeyCat = GetKeysAVar( 'keycatname.'Keyset'.'n)
1698 KeyStrings = GetKeysAVar( 'catkeys.'Keyset'.'KeyCat)
1699 if KeyStrings = '' then
1700 iterate
1701 endif
1702
1703 KeyCatText = KeyCat
1704 if KeyCat = 'Newline' then
1705 mmax = 2
1706 else
1707 mmax = 1
1708 endif
1709 do m = 1 to mmax
1710 if KeyCat = 'Newline' then
1711 if m = 1 then
1712 mode = 'stream'
1713 else
1714 mode = 'line'
1715 endif
1716 KeyCatText = KeyCat' in 'mode' mode'
1717 endif
1718 insertline '', .last + 1
1719 insertline Indent''KeyCatText, .last + 1
1720 insertline '', .last + 1
1721
1722 do w = 1 to words( KeyStrings)
1723 KeyString = word( KeyStrings, w)
1724 Cmd = GetKeysAVar( 'keydef.'KeyString)
1725 if Cmd = '' then
1726 Cmd = GetKeysAVar( 'mousedef.'KeyString)
1727 endif
1728
1729 if subword( upcase( Cmd), 1, 1) = 'NEWLINE' then
1730 KeyPath = '\NEPMD\User\SpecialKeys'
1731 if mode = 'stream' then
1732 KeyPath = KeyPath'\Stream'
1733 else
1734 KeyPath = KeyPath'\Line'
1735 endif
1736 KeyPath = KeyPath'\'KeyString
1737 next = QueryConfigKey( KeyPath)
1738 if next = '' then
1739 next = 'Split,KeepIndent'
1740 endif
1741 parse value next with SplitCfg','ColCfg','fCmd','NewlineCmd
1742 if fCmd <> 1 then
1743 fCmd = 0
1744 endif
1745 if fCmd then
1746 Cmd = NewlineCmd
1747 else
1748 Cmd = 'Newline' SplitCfg','ColCfg
1749 endif
1750
1751 elseif wordpos( subword( upcase( Cmd), 1, 1), 'TAB BACKTAB') then
1752 KeyPath = '\NEPMD\User\SpecialKeys\'KeyString
1753 next = QueryConfigKey( KeyPath)
1754 Cmd = Cmd next
1755 endif
1756
1757 CnvKeyString = ConvertKeyString( KeyString)
1758 -- Longest KeyString = 21
1759 KeyStringSpc = leftstr( KeyString, Max( 21 + length( Indent), length( KeyString)))''Indent
1760 -- Longest CnvKeyString = 24
1761 CnvKeyStringSpc = leftstr( CnvKeyString, Max( 24 + length( Indent), length( CnvKeyString)))''Indent
1762 -- Display only converted KeyString and Cmd columns:
1763 insertline Indent''Indent''CnvKeyStringSpc''Cmd, .last + 1
1764 -- Display an additional KeyString column:
1765 --insertline Indent''Indent''KeyStringSpc''CnvKeyStringSpc''Cmd, .last + 1
1766 enddo
1767 enddo
1768 enddo
1769 insertline '', .last + 1
1770 tmpfid.modify = 0
1771 --activatefile tmpfid
1772 .cursory = 4 -- Scroll almost to the top (must come before setting the line)
1773 .line = savedlast + 1
1774 .col = 1
1775 display 3
1776
1777; ---------------------------------------------------------------------------
1778; This must be used instead of the internally defined deleteaccel statement.
1779; Disadvantage: This closes the menu, even if nodismiss is set for a menu
1780; item. This is caused by the array var procs, because they switch
1781; temporarily to a hidden file.
1782defc DeleteAccel, DelKeyset
1783 universal activeaccel
1784 if arg( 1) = '' | lowcase( arg( 1)) = 'defaccel' then
1785 Keyset = activeaccel
1786 else
1787 Keyset = arg( 1)
1788 endif
1789 Keyset = lowcase( Keyset)
1790 deleteaccel Keyset
1791 activeaccel = ''
1792
1793 -- Change array vars for this keyset name
1794 DelKeysAVar( 'keysets', Keyset)
1795 SubKeysets = GetKeysAVar( 'keyset.'Keyset)
1796 -- For all keyset commands
1797 do k = 1 to words( SubKeysets)
1798 SubKeyset = word( SubKeysets, k)
1799 -- Remove keyset name from array var for this keyset cmd
1800 DelKeysAVar( 'keysetused.'SubKeyset, Keyset)
1801 enddo
1802 DropKeysAVar( 'keyset.'Keyset)
1803
1804 -- For all categories
1805 LastNum = GetKeysAVar( 'keycatname.'Keyset'.0')
1806 do n = 1 to LastNum
1807 KeyCat = GetKeysAVar( 'keycatname.'Keyset'.'n)
1808 KeyStrings = GetKeysAVar( 'catkeys.'Keyset'.'KeyCat)
1809 if KeyStrings = '' then
1810 iterate
1811 endif
1812
1813 -- For all keystrings
1814 do w = 1 to words( KeyStrings)
1815 KeyString = word( KeyStrings, w)
1816
1817 -- Remove KeyString array vars
1818 Cmd = GetKeysAVar( 'keydef.'KeyString)
1819 if Cmd = '' then
1820 Cmd = GetKeysAVar( 'mousedef.'KeyString)
1821 DelKeysAVar( 'mousecmd.'Cmd, KeyString)
1822 DropKeysAVar( 'mousedef.'KeyString)
1823 else
1824 DelKeysAVar( 'keycmd.'Cmd, KeyString)
1825 DropKeysAVar( 'keydef.'KeyString)
1826 endif
1827
1828 -- Remove KeyString from category list
1829 DelKeysAVar( 'catkeys.'Keyset'.'KeyCat, KeyString)
1830 -- Remove var name from array
1831 DropKeysAVar( 'keycat.'Keyset'.'KeyString)
1832 enddo
1833
1834 enddo
1835
1836; ---------------------------------------------------------------------------
1837; Ensure that default entry is present in AddKeyDefsList
1838definit
1839 'InitAddKeyDefs'
1840
1841defc InitAddKeyDefs
1842 DefaultNameList = lowcase( 'cua') -- only basenames without 'keys'
1843
1844 KeyPathList = '\NEPMD\User\Keysets\AddKeyDefs\List'
1845 KeyPathSelected = '\NEPMD\User\Keysets\AddKeyDefs\Selected'
1846 AddKeyDefsList = QueryConfigKey( KeyPathList)
1847 SelectedAddKeyDefs = QueryConfigKey( KeyPathSelected)
1848
1849 -- Remove 'keys' from SelectedAddKeyDefs
1850 if rightstr( SelectedAddKeyDefs, 4) = 'keys' then
1851 parse value SelectedAddKeyDefs with SelectedAddKeyDefs'keys'
1852 --dprintf( 'definit: Write to NEPMD.INI: SelectedAddKeyDefs = 'SelectedAddKeyDefs)
1853 WriteConfigKey( KeyPathSelected, SelectedAddKeyDefs)
1854 endif
1855
1856 -- Remove 'keys' from every word of AddKeyDefsList
1857 List = ''
1858 do w = 1 to words( AddKeyDefsList)
1859 Next = word( AddKeyDefsList, w)
1860 parse value Next with Next'keys'
1861 List = strip( List Next)
1862 enddo
1863 if AddKeyDefsList <> List then
1864 WriteConfigKey( KeyPathList, List)
1865 endif
1866
1867 -- Maybe add every item of DefaultNameList to AddKeyDefsList
1868 List = AddKeyDefsList
1869 do w = 1 to words( DefaultNameList)
1870 ThisName = word( DefaultNameList, w)
1871 if not wordpos( ThisName, List) then
1872 List = strip( List ThisName)
1873 endif
1874 enddo
1875 if List <> AddKeyDefsList then
1876 WriteConfigKey( KeyPathList, List)
1877 endif
1878
1879; ---------------------------------------------------------------------------
1880; Also called in NEWMENU.E.
1881defproc GetAddKeyDefs
1882 KeyPathSelected = '\NEPMD\User\Keysets\AddKeyDefs\Selected'
1883 SelectedAddKeyDefs = QueryConfigKey( KeyPathSelected)
1884 return SelectedAddKeyDefs
1885
1886; ---------------------------------------------------------------------------
1887defc RemoveAddKeyDefs
1888 KeyPathList = '\NEPMD\User\Keysets\AddKeyDefs\List'
1889 KeyPathSelected = '\NEPMD\User\Keysets\AddKeyDefs\Selected'
1890
1891 AddKeyDefs = strip( arg( 1))
1892 AddKeyDefsList = QueryConfigKey( KeyPathList)
1893 SelectedAddKeyDefs = QueryConfigKey( KeyPathSelected)
1894
1895 if linked( AddKeyDefs'keys') > 0 then
1896 'unlink' AddKeyDefs'keys'
1897 endif
1898
1899 -- Remove from list
1900 wp = wordpos( AddKeyDefs, AddKeyDefsList)
1901 if wp > 0 then
1902 AddKeyDefsList = SpaceStr( DelWord( AddKeyDefsList, wp, 1))
1903 WriteConfigKey( KeyPathList, AddKeyDefsList)
1904 endif
1905
1906 -- Remove from macroadd.lst
1907 call DeleteFromMacroListFile( AddKeyDefs'keys')
1908
1909 if AddKeyDefs = SelectedAddKeyDefs then
1910 'SetAddKeyDefs' -- reset
1911 endif
1912
1913; ---------------------------------------------------------------------------
1914defc SetAddKeyDefs
1915 universal activeaccel
1916
1917 KeyPathList = '\NEPMD\User\Keysets\AddKeyDefs\List'
1918 KeyPathSelected = '\NEPMD\User\Keysets\AddKeyDefs\Selected'
1919
1920 AddKeyDefs = strip( arg( 1))
1921 --dprintf( 'SetAddKeyDefs: arg( 1) = 'arg( 1))
1922 AddKeyDefsList = QueryConfigKey( KeyPathList)
1923 SelectedAddKeyDefs = QueryConfigKey( KeyPathSelected)
1924 DefinedKeysets = GetKeysAVar( 'keysets')
1925
1926 -- Save current keyset
1927 SavedKeyset = activeaccel
1928 getfileid fid
1929 CurKeyset = GetKeysAVar( fid'.keyset')
1930 CurSubKeysets = GetKeysAVar( 'keyset.'CurKeyset)
1931 --dprintf( 'SetAddKeyDefs: CurKeyset = 'CurKeyset', CurSubKeysets = 'CurSubKeysets', activeaccel = 'activeaccel)
1932
1933 -- Nothing changed: don't process further
1934 if AddKeyDefs = SelectedAddKeyDefs then
1935 --dprintf( 'SetAddKeyDefs: AddKeyDefs = 'AddKeyDefs', SelectedAddKeyDefs = 'SelectedAddKeyDefs)
1936 return
1937 endif
1938
1939 -- Delete all key defs first and re-apply all defs of main keyset
1940 'DisableSwitchKeyset'
1941
1942 -- Reset list of defined keysets to make SetKeyset2 execute DefKeyset.
1943 -- The keyset of the current file is defined and switched immediately.
1944 -- For all other files in the ring that is processed on their next
1945 -- select event.
1946 call SetKeysAVar( 'keysets', '')
1947
1948 -- Reset keyset 'std'
1949 --dprintf( 'SetAddKeyDefs: Reset keyset std, execute SetKeyset2 std std')
1950 'SetKeyset2 std std'
1951
1952 'EnableSwitchKeyset'
1953
1954 -- Change list of subkeysets and define each key def
1955 do w = 1 to words( DefinedKeysets)
1956 Keyset = word( DefinedKeysets, w)
1957 SubKeysets = strip( GetKeysAVar( 'keyset.'Keyset))
1958 --dprintf( 'SetAddKeyDefs: w = 'w', Keyset = 'Keyset', SubKeysets = 'SubKeysets', AddKeyDefs = 'AddKeyDefs', SelectedAddKeyDefs = 'SelectedAddKeyDefs)
1959
1960 -- Remove previous add. keydefs name first
1961 wp = wordpos( SelectedAddKeyDefs, SubKeysets)
1962 if wp > 0 then
1963 SubKeysets = SpaceStr( delword( SubKeysets, wp, 1))
1964 endif
1965
1966 -- Add add. keydefs name next after 'std'
1967 if AddKeyDefs <> '' then
1968 wp = wordpos( 'std', SubKeysets)
1969 LeftWords = subword( SubKeysets, 1, wp)
1970 RightWords = subword( SubKeysets, wp + 1)
1971 SubKeysets = SpaceStr( LeftWords AddKeyDefs RightWords)
1972 endif
1973
1974 if Keyset = SavedKeyset then
1975 --dprintf( 'SetAddKeyDefs: 1) execute SetKeyset' Keyset SubKeysets)
1976 'SetKeyset' Keyset SubKeysets -- active, redefine and exec keyset cmds
1977 else
1978 --dprintf( 'SetAddKeyDefs: 2) call SetKeysAVar( keyset.'Keyset', 'SubKeysets')')
1979 call SetKeysAVar( 'keyset.'Keyset, SubKeysets) -- not active, just redefine
1980 endif
1981 enddo
1982
1983 call WriteConfigKey( KeyPathSelected, AddKeyDefs)
1984
1985; ---------------------------------------------------------------------------
1986; Open a listbox to select aditional key defs. The additional defs must be
1987; placed in a separate E file, without using the defkeys statement. When
1988; simply linking such a file, all special keysets for already loaded files
1989; would be lost and the keyset EDIT_KEYS is set for all loaded files.
1990; Therefore EPM will be restarted to make the changes take effect as
1991; expected. For unlinking a key def file, no restart is required.
1992defc SelectKeyDefs
1993 universal activeaccel
1994
1995 None = '-none-'
1996
1997 parse arg Action Basename
1998 Action = upcase( Action)
1999 lp = lastpos( '\', strip( Basename))
2000 Basename = substr( Basename, lp + 1)
2001 Basename = lowcase( Basename)
2002 if Basename = '' then
2003 elseif rightstr( Basename, 2) = '.e' then
2004 Basename = leftstr( Basename, length( Basename) - 2)
2005 elseif rightstr( Basename, 3) = '.ex' then
2006 Basename = leftstr( Basename, length( Basename) - 3)
2007 endif
2008 if rightstr( Basename, 4) <> 'keys' then
2009 Basename = Basename'keys'
2010 endif
2011
2012 -- Read available files from NEPMD.INI
2013 KeyPathList = '\NEPMD\User\Keysets\AddKeyDefs\List'
2014 KeyPathSelected = '\NEPMD\User\Keysets\AddKeyDefs\Selected'
2015 AddKeyDefsList = QueryConfigKey( KeyPathList) -- space-separated list
2016 SelectedAddKeyDefs = QueryConfigKey( KeyPathSelected)
2017 SelectedAddKeyDefs = lowcase( SelectedAddKeyDefs)
2018 if SelectedAddKeyDefs = '' then
2019 SelectedAddKeyDefs = None
2020 endif
2021
2022 if Action = 'ADD' & Basename <> '' then
2023 parse value Basename with NextAddKeyDefs'keys'
2024 CompleteKeysetNames = 'std'
2025 if wordpos( NextAddKeyDefs, CompleteKeysetNames) then
2026 Title = 'Adding additional key definitions'
2027 Text = 'This file "'NextAddKeyDefs'keys.e" defines the'
2028 Text = Text' "'NextAddKeyDefs'" keyset. It''s not a'
2029 Text = Text' file with additional keyset definitions, but'
2030 Text = Text' defines a basic keyset instead.'\n\n
2031 Text = Text'You may want to start with a renamed copy of'
2032 Text = Text' cuakeys.e instead.'
2033 Style = MB_OKCANCEL+MB_WARNING+MB_DEFBUTTON1+MB_MOVEABLE
2034 rcx = WinMessageBox( Title,
2035 Text,
2036 Style)
2037 if rcx = MBID_OK then
2038 -- Open this dialog again
2039 'postme SelectKeyDefs'
2040 return
2041 else -- Cancel
2042 return
2043 endif
2044 endif
2045 if not wordpos( NextAddKeyDefs, AddKeyDefsList) then
2046 AddKeyDefsList = strip( AddKeyDefsList NextAddKeyDefs)
2047 WriteConfigKey( KeyPathList, AddKeyDefsList)
2048 endif
2049
2050 if not IsExFileInternal( Basename) then
2051 Title = 'Adding additional key definitions'
2052 Text = 'For the additional key definition macro "'Basename'" no'
2053 Text = Text || ' entry in a LST file was found. In order to make'
2054 Text = Text || ' the RecompileNew macro aware of that file, it'
2055 Text = Text || ' should be added to "macroadd.lst".'\n\n
2056 Text = Text || 'Should the entry be added automatically?'
2057 Style = MB_YESNO+MB_QUERY+MB_DEFBUTTON1+MB_MOVEABLE
2058 rcx = WinMessageBox( Title,
2059 Text,
2060 Style)
2061 if rcx = 6 then -- Yes
2062 call AddToMacroListFile( Basename)
2063 if rc <> 0 then
2064 'SayError Error: AddToMacroListFile( 'Basename') returned rc = 'rc
2065 return
2066 endif
2067 elseif rcx = 7 then -- No
2068 endif
2069 endif
2070
2071 Title = 'Adding additional key definitions'
2072 Text = 'Before the macro file "'Basename'" can be loaded,'
2073 Text = Text || ' it has to be compiled.'\n\n
2074 Text = Text || 'Should RecompileNew be called now?'
2075 Style = MB_YESNO+MB_WARNING+MB_DEFBUTTON1+MB_MOVEABLE
2076 rcx = WinMessageBox( Title,
2077 Text,
2078 Style)
2079 if rcx = 6 then -- Yes
2080 -- Execute RecompileNew and open this dialog again
2081 'RecompileNew'
2082 'postme SelectKeyDefs'
2083 return
2084 elseif rcx = 7 then -- No
2085 endif
2086 endif
2087
2088 -- Open listbox
2089 Sep = '/'
2090 -- Add None first
2091 Entries = Sep''None
2092 do w = 1 to words( AddKeyDefsList)
2093 Next = word( AddKeyDefsList, w)'keys'
2094 -- Add Next with 'keys' appended
2095 Entries = Entries''Sep''Next
2096 enddo
2097
2098 DefaultItem = 1
2099 if SelectedAddKeyDefs <> '' then
2100 wp = wordpos( SelectedAddKeyDefs, AddKeyDefsList)
2101 if wp > 0 then
2102 DefaultItem = wp + 1
2103 endif
2104 endif
2105 DefaultButton = 1
2106 HelpId = 0
2107 Title = 'Select additional key definitions'copies( ' ', 20)
2108 Text = 'Current key def additions:' SelectedAddKeyDefs
2109
2110 refresh
2111 Result = ListBox( Title,
2112 Entries,
2113 '/~Set/~Add.../~Edit/~Remove/'CANCEL__MSG, -- buttons
2114 0, 0, --5, 5, -- top, left,
2115 Min( words( AddKeyDefsList), 15), 50, -- height, width
2116 GethWndC( APP_HANDLE) || atoi( DefaultItem) ||
2117 atoi( DefaultButton) || atoi( HelpId) ||
2118 Text\0)
2119 refresh
2120
2121 -- Check result
2122 button = asc( leftstr( Result, 1))
2123 EOS = pos( \0, Result, 2) -- CHR(0) signifies End Of String
2124 Selected = substr( Result, 2, EOS - 2)
2125 if button = 1 then -- Set
2126 if Selected = None then
2127 'SetAddKeyDefs'
2128 if isadefproc( 'MenuText_keydefs') then
2129 MenuText_keydefs()
2130 endif
2131 Msg = 'No keyset additions file active.'
2132 'SayHint' Msg
2133 else
2134 -- Check if .E file exists
2135 findfile EFile, Selected'.e', 'EPMPATH'
2136 if rc then
2137 -- Check if .EX file exists
2138 findfile EFile, Selected'.ex', 'EPMPATH'
2139 if rc then
2140 'SayError Key definition file 'upcase( Selected)'.E or 'upcase( Selected)'.EX not found.'
2141 rc = 2
2142 return
2143 endif
2144 endif
2145 parse value lowcase( Selected) with AddKeyDefs'keys'
2146 'SetAddKeyDefs' AddKeyDefs
2147 if isadefproc( 'MenuText_keydefs') then
2148 MenuText_keydefs()
2149 endif
2150 Msg = 'Keyset additions file 'upcase( Selected)'.EX activated.'
2151 'SayHint' Msg
2152 endif
2153 elseif button = 2 then -- Add
2154 -- Open fileselector to select an e or ex filename
2155 -- Call this Cmd again, but with args to renew the list
2156 Text = 'Select a file with additional key definitions'
2157 'FileDlg 'Text', SelectKeyDefs ADD, 'Get_Env('NEPMD_USERDIR')'\macros\?*keys.e'
2158 rc = 0
2159 return
2160 elseif button = 3 & Selected <> None then -- Edit
2161 -- Load file
2162 'EditCreateUserMacro 'Selected'.e'
2163 return rc
2164 elseif button = 4 & Selected <> None then -- Remove
2165 parse value lowcase( Selected) with AddKeyDefs'keys'
2166 -- Confirm remove from list
2167 if MBID_YES = WinMessageBox( 'Remove keyset addition entry', -- title
2168 'You''re about to remove' Selected 'from the list.' \n ||
2169 ARE_YOU_SURE__MSG,
2170 MB_YESNO + MB_QUERY + MB_DEFBUTTON2 + MB_MOVEABLE) then
2171 -- Remove from list
2172 'RemoveAddKeyDefs' AddKeyDefs
2173 if isadefproc( 'MenuText_keydefs') then
2174 MenuText_keydefs()
2175 endif
2176 endif
2177 -- Call this Cmd again
2178 'SelectKeyDefs'
2179 else -- Cancel
2180 endif
2181
2182; ---------------------------------------------------------------------------
2183; Definitions used for key commands
2184; ---------------------------------------------------------------------------
2185
2186; ---------------------------------------------------------------------------
2187; This command allows to define 2 commands, separated by a bar char. The
2188; first command applies in stream mode and the second in line mode.
2189defc StreamLine
2190 universal stream_mode
2191 parse arg cmd1'|'cmd2
2192 cmd1 = strip( cmd1)
2193 cmd2 = strip( cmd2)
2194 if stream_mode then
2195 cmd1
2196 else
2197 cmd2
2198 endif
2199
2200; ---------------------------------------------------------------------------
2201defproc Shifted
2202 universal curkey
2203
2204 -- Works for WM_CHAR messages:
2205 ks = getkeystate( VK_SHIFT)
2206 fshifted1 = (ks <> 3 & ks <> 4)
2207
2208 -- Works for accelerator keys:
2209 parse value curkey with KeyString \1 Cmd
2210 fshifted2 = (pos( 's_', KeyString) > 0)
2211
2212 return (fshifted1 | fshifted2)
2213
2214; ---------------------------------------------------------------------------
2215defproc UpDownKey( DownFlag)
2216 universal save_cursor_column
2217 universal cursoreverywhere
2218 universal prevkey
2219
2220 NumLines = arg( 2)
2221 if NumLines = '' then
2222 NumLines = 1
2223 elseif not IsNum( NumLines) then
2224 NumLines = 1
2225 endif
2226
2227 parse value prevkey with PrevKeyString \1 .
2228 fupdown = (wordpos( PrevKeyString, 'up down s_up s_down') > 0)
2229 if not cursoreverywhere then
2230 if not fupdown then
2231 save_cursor_column = .col
2232 endif
2233 endif
2234
2235 if DownFlag then
2236 do n = 1 to NumLines
2237 down
2238 enddo
2239 else
2240 do n = 1 to NumLines
2241 up
2242 enddo
2243 endif
2244
2245 if .line & not cursoreverywhere then
2246 l = length( textline( .line))
2247 if fupdown & l >= save_cursor_column then
2248 .col = save_cursor_column
2249 elseif fupdown | l < .col then
2250 endline
2251 endif
2252 endif
2253
2254; ---------------------------------------------------------------------------
2255defproc ScrollUpDownKey( DownFlag)
2256
2257 NumLines = arg( 2)
2258 if NumLines = '' then
2259 NumLines = 1
2260 elseif not IsNum( NumLines) then
2261 NumLines = 1
2262 endif
2263
2264 if DownFlag then
2265 do n = 1 to NumLines
2266 oldcursory = .cursory
2267 if .line - .cursory + .windowheight < .last then
2268 .cursory = .windowheight
2269 down
2270 .cursory = oldcursory
2271 elseif .line < .last then
2272 down
2273 endif
2274 enddo
2275 else
2276 oldcursory = .cursory
2277 do n = 1 to NumLines
2278 if .line - .cursory > -1 then
2279 .cursory = 1
2280 up
2281 .cursory = oldcursory
2282 elseif .line then
2283 up
2284 endif
2285 enddo
2286 endif
2287
2288; ---------------------------------------------------------------------------
2289defproc Extend_Mark( startline, startcol, forward)
2290 universal cursoreverywhere
2291 universal curkey
2292
2293 KeyPath = '\NEPMD\User\Mark\ShiftMarkAlwaysExtends'
2294 fAlwaysExtend = (QueryConfigKey( KeyPath) = 1)
2295 getfileid curfileid
2296 getmarkg firstline, lastline, firstcol, lastcol, markfileid
2297 parse value curkey with CurKeyString \1 .
2298 fs_up = (CurKeyString = 's_up')
2299 fs_down = (CurKeyString = 's_down')
2300
2301 funmark = 1
2302 if markfileid <> curfileid then
2303 funmark = 1
2304 elseif QueryUnmarkOnAnyKey() then
2305 -- keep mark and extend it (any unshifted key caused unmark before)
2306 funmark = 0
2307 elseif fAlwaysExtend then
2308 -- keep mark and extend it
2309 funmark = 0
2310
2311 -- The following was added for the feature "Shift-Mark extends at mark
2312 -- boundaries only" (== "Shift-mark extends always" = deactivated):
2313 elseif not cursoreverywhere then
2314 if startline = firstline & startcol = firstcol then
2315 funmark = 0
2316 elseif startline = lastline & startcol = lastcol then
2317 funmark = 0
2318 endif
2319 elseif cursoreverywhere then
2320 l = length( textline( startline))
2321 if startline = firstline & startcol = firstcol then
2322 funmark = 0
2323 elseif startline = firstline & startcol > firstcol & startcol > l + 1 then
2324 funmark = 0
2325 elseif startline = firstline + 1 & firstcol = 0 then
2326 -- apparently never reached
2327 funmark = 0
2328 elseif startline = lastline & startcol = lastcol then
2329 funmark = 0
2330 elseif startline = lastline & startcol > lastcol & startcol > l + 1 then
2331 funmark = 0
2332 elseif startline = lastline - 1 & lastcol = 0 then
2333 funmark = 0
2334 endif
2335 endif
2336
2337 if funmark then
2338 unmark
2339 endif
2340
2341 if not marktype() then
2342 call pSet_Mark( startline, .line, startcol, .col, 'CHARG', curfileid)
2343 return
2344 endif
2345
2346 if (fs_up & .line = firstline - 1) | (fs_down & .line = firstline + 1) then
2347 if length( textline( firstline)) < .col then
2348 firstcol = .col
2349 endif
2350 endif
2351
2352 if startline > firstline | ((startline = firstline) & (startcol > firstcol)) then -- at end of mark
2353 if not forward then
2354 if firstline = .line & firstcol = .col then
2355 unmark
2356 return
2357 endif
2358 endif
2359 call pSet_Mark( firstline, .line, firstcol, .col, 'CHARG', curfileid)
2360 else -- at beginning of mark
2361 if forward then
2362 if lastline = .line & lastcol = .col - 1 then
2363 unmark
2364 return
2365 endif
2366 endif
2367 call pSet_Mark( lastline, .line, lastcol, .col, 'CHARG', curfileid)
2368 endif
2369
2370; ---------------------------------------------------------------------------
2371; c_home, c_end, c_left & c_right do different things if the shift key is depressed.
2372; The logic is extracted here mainly due to the complexity of the COMPILE IF's
2373defproc Begin_Shift( var startline, var startcol, var shift_flag)
2374; unused
2375/*
2376 universal cua_marking_switch
2377 shift_flag = Shifted()
2378 if shift_flag or not cua_marking_switch then
2379 startline = .line; startcol = .col
2380 else
2381 unmark
2382 endif
2383*/
2384
2385; ---------------------------------------------------------------------------
2386defproc End_Shift( startline, startcol, shift_flag, forward_flag)
2387; unused
2388/*
2389; Make this work regardless of which marking mode is active:
2390compile if 0 -- WANT_CUA_MARKING = 'SWITCH'
2391 universal cua_marking_switch
2392 if shift_flag & cua_marking_switch then
2393compile else
2394 if shift_flag then
2395compile endif
2396 call Extend_Mark( startline, startcol, forward_flag)
2397 endif
2398*/
2399
2400; ---------------------------------------------------------------------------
2401; For compatibility.
2402defproc Process_Mark_Like_Cua
2403 fMarkDeleted = ReplaceMark()
2404 if fMarkDeleted then
2405 rcx = 1
2406 else
2407 rcx = ''
2408 endif
2409 return rcx
2410
2411; ---------------------------------------------------------------------------
2412defc SwitchMarkingMode
2413 universal menuloaded
2414 universal cua_marking_switch
2415
2416 NewMarkingMode = upcase( strip( leftstr( arg( 1), 1)))
2417 CurrentMarkingMode = QueryMarkingMode()
2418 if NewMarkingMode <> CurrentMarkingMode then
2419 if NewMarkingMode = 'A' then
2420 'ApplyMarkingBitStr' GetDefaultMarkingBitStr( 'ADV')
2421 elseif NewMarkingMode = 'C' then
2422 'ApplyMarkingBitStr' GetDefaultMarkingBitStr( 'CUA')
2423 endif
2424
2425 -- For compatibility
2426 if NewMarkingMode = 'C' then
2427 cua_marking_switch = 1
2428 else
2429 cua_marking_switch = 0
2430 endif
2431
2432 -- Refresh display
2433 'RefreshInfoLine MARKINGMODE'
2434
2435 -- Refresh menus
2436 if menuloaded then
2437 -- Set menu attributes and text for the case MIA_NODISMISS attribute is on
2438 if GetMenuAVar( 'mid_mark') then
2439 'menuinit_mark'
2440 endif
2441 -- The menu from where the action stems can't be queried with activemenu.
2442 -- After opening the 'prefspopup' menu, the universal is switched back to
2443 -- 'default'.
2444 if GetMenuAVar( 'mid_basicconfig') then
2445 'menuinit_basicconfig'
2446 'menuinit_markingsettings'
2447 endif
2448 endif
2449 endif
2450
2451; ---------------------------------------------------------------------------
2452; Returns 'A' | 'C' | ''
2453defproc QueryMarkingMode
2454 CurrentMarkingMode = ''
2455 CurrentMarkingBitStr = GetCurrentMarkingBitStr()
2456 -- E precision is max. 9 digits, DigitComp is required
2457 fAdvancedMarking = not DigitComp( CurrentMarkingBitStr,
2458 GetDefaultMarkingBitStr( 'ADV'))
2459 fCuaMarking = not DigitComp( CurrentMarkingBitStr,
2460 GetDefaultMarkingBitStr( 'CUA'))
2461 if fAdvancedMarking then
2462 CurrentMarkingMode = 'A'
2463 elseif fCuaMarking then
2464 CurrentMarkingMode = 'C'
2465 endif
2466 return CurrentMarkingMode
2467
2468; ---------------------------------------------------------------------------
2469defproc GetCurrentMarkingBitStr
2470 KeyPath = '\NEPMD\User\Mark\DefaultPaste'
2471 DefaultPaste = QueryConfigKey( KeyPath)
2472
2473 KeyPath = '\NEPMD\User\Mark\ShiftMarkAlwaysExtends'
2474 fShiftMarkExtends = QueryConfigKey( KeyPath)
2475
2476 KeyPath = '\NEPMD\User\Mark\LineInsert'
2477 InsertMarkedLines = QueryConfigKey( KeyPath)
2478
2479 KeyPath = '\NEPMD\User\Mark\ReplaceMark'
2480 fReplaceMark = QueryConfigKey( KeyPath)
2481
2482 KeyPath = '\NEPMD\User\Mark\DirectMarkActions'
2483 fDirectMarkActions = QueryConfigKey( KeyPath)
2484
2485 KeyPath = '\NEPMD\User\Mark\UnmarkOnAnyKey'
2486 fUnmarkOnAnyKey = QueryConfigKey( KeyPath)
2487
2488 KeyPath = '\NEPMD\User\Mark\UnmarkAfterMove'
2489 fUnmarkAfterMove = QueryConfigKey( KeyPath)
2490
2491 KeyPath = '\NEPMD\User\Mark\DefaultMouseMark'
2492 DefaultMouseMark = QueryConfigKey( KeyPath)
2493
2494 KeyPath = '\NEPMD\User\Mark\GoToMousePos'
2495 fGoToMouseMark = QueryConfigKey( KeyPath)
2496
2497 KeyPath = '\NEPMD\User\MB1DoubleClick\Mark'
2498 DoubleClickMarks = QueryConfigKey( KeyPath)
2499
2500 f4os2MouseMark = Query4os2MouseMark()
2501
2502 KeyPath = '\NEPMD\User\MB1DoubleClick\UnmarkOnSpace'
2503 fDoubleClickUnmarks = QueryConfigKey( KeyPath)
2504
2505 KeyPath = '\NEPMD\User\SearchDialog\SearchMarkIfMarked'
2506 fSearchMarkIfMarked = QueryConfigKey( KeyPath)
2507
2508 KeyPath = '\NEPMD\User\SearchDialog\SearchMarkedWords'
2509 fSearchMarkedWords = QueryConfigKey( KeyPath)
2510
2511 CurrentMarkingBitStr = '' ||
2512 DefaultPaste ||
2513 fShiftMarkExtends ||
2514 InsertMarkedLines ||
2515 fReplaceMark ||
2516 fDirectMarkActions ||
2517 fUnmarkOnAnyKey ||
2518 fUnmarkAfterMove ||
2519 DefaultMouseMark ||
2520 fGoToMouseMark ||
2521 DoubleClickMarks ||
2522 f4os2MouseMark ||
2523 fDoubleClickUnmarks ||
2524 fSearchMarkIfMarked ||
2525 fSearchMarkedWords
2526
2527 return CurrentMarkingBitStr
2528
2529; -------------------------------------------------------------------------------------- Preferences ------------------
2530const
2531compile if not defined( PRESET_BITSTR_USER_CUA)
2532 PRESET_BITSTR_USER_CUA = 011100000
2533compile endif
2534compile if not defined( PRESET_BITSTR_PROG_CUA)
2535 PRESET_BITSTR_PROG_CUA = 101111111
2536compile endif
2537compile if not defined( PRESET_BITSTR_PROG_STD)
2538 PRESET_BITSTR_PROG_STD = 100011111
2539compile endif
2540compile if not defined( MARKING_BITSTR_ADV)
2541 MARKING_BITSTR_ADV = '???01 0? ?0?? 1 ??'
2542compile endif
2543compile if not defined( MARKING_BITSTR_CUA)
2544 MARKING_BITSTR_CUA = 'C0A10 10 C1W? 0 ??'
2545compile endif
2546
2547; ---------------------------------------------------------------------------
2548defproc GetDefaultMarkingBitStr
2549 MarkingType = upcase( arg( 1))
2550 DefaultMarkingBitStr = ''
2551 if MarkingType = 'ADV' then
2552 DefaultMarkingBitStr = MARKING_BITSTR_ADV
2553 elseif MarkingType = 'CUA' then
2554 DefaultMarkingBitStr = MARKING_BITSTR_CUA
2555 endif
2556 return DefaultMarkingBitStr
2557
2558; ---------------------------------------------------------------------------
2559defc ApplyMarkingBitStr
2560 do once = 1 to 1
2561
2562 -- Query CurrentMarkingBitStr
2563 CurrentMarkingBitStr = SpaceStr( arg( 1), 0)
2564 -- Check CurrentMarkingBitStr
2565 if length( CurrentMarkingBitStr) <>
2566 length( SpaceStr( GetDefaultMarkingBitStr( 'ADV'), 0)) then
2567 leave
2568 endif
2569 -- Parse CurrentMarkingBitStr
2570 DefaultPaste = substr( CurrentMarkingBitStr, 1, 1)
2571 fShiftMarkExtends = substr( CurrentMarkingBitStr, 2, 1)
2572 InsertMarkedLines = substr( CurrentMarkingBitStr, 3, 1)
2573 fReplaceMark = substr( CurrentMarkingBitStr, 4, 1)
2574 fDirectMarkActions = substr( CurrentMarkingBitStr, 5, 1)
2575 fUnmarkOnAnyKey = substr( CurrentMarkingBitStr, 6, 1)
2576 fUnmarkAfterMove = substr( CurrentMarkingBitStr, 7, 1)
2577 DefaultMouseMark = substr( CurrentMarkingBitStr, 8, 1)
2578 fGoToMouseMark = substr( CurrentMarkingBitStr, 9, 1)
2579 DoubleClickMarks = substr( CurrentMarkingBitStr, 10, 1)
2580 f4os2MouseMark = substr( CurrentMarkingBitStr, 11, 1)
2581 fDoubleClickUnmarks = substr( CurrentMarkingBitStr, 12, 1)
2582 fSearchMarkIfMarked = substr( CurrentMarkingBitStr, 13, 1)
2583 fSearchMarkedWords = substr( CurrentMarkingBitStr, 14, 1)
2584
2585 -- Apply bits
2586
2587 KeyPath = '\NEPMD\User\Mark\DefaultPaste'
2588 if DefaultPaste = '?' then
2589 -- nop
2590 elseif DefaultPaste <> QueryConfigKey( KeyPath) then
2591 WriteConfigKey( KeyPath, DefaultPaste)
2592 RefreshMenuAccelString( 'paste')
2593 RefreshMenuAccelString( 'pastelines')
2594 RefreshMenuAccelString( 'pasteblock')
2595 endif
2596
2597 KeyPath = '\NEPMD\User\Mark\ShiftMarkAlwaysExtends'
2598 if fShiftMarkExtends = '?' then
2599 -- nop
2600 elseif fShiftMarkExtends <> QueryConfigKey( KeyPath) then
2601 'toggle_shift_mark_extends'
2602 endif
2603
2604 KeyPath = '\NEPMD\User\Mark\LineInsert'
2605 if InsertMarkedLines = '?' then
2606 -- nop
2607 elseif InsertMarkedLines <> QueryConfigKey( KeyPath) then
2608 'toggle_lineinsert'
2609 endif
2610
2611 if fReplaceMark = '?' then
2612 -- nop
2613 else
2614 'SwitchReplaceMark 'fReplaceMark
2615 endif
2616
2617 if fDirectMarkActions = '?' then
2618 -- nop
2619 else
2620 'SwitchDirectMarkActions 'fDirectMarkActions
2621 endif
2622
2623 if fUnmarkOnAnyKey = '?' then
2624 -- nop
2625 else
2626 'SwitchUnmarkOnAnyKey 'fUnmarkOnAnyKey
2627 endif
2628
2629 KeyPath = '\NEPMD\User\Mark\UnmarkAfterMove'
2630 if fUnmarkAfterMove = '?' then
2631 -- nop
2632 elseif fUnmarkAfterMove <> QueryConfigKey( KeyPath) then
2633 'toggle_unmark_after_move'
2634 endif
2635
2636 if DefaultMouseMark = '?' then
2637 -- nop
2638 else
2639 'SwitchDefaultMouseMark 'DefaultMouseMark
2640 endif
2641
2642 if fGoToMouseMark = '?' then
2643 -- nop
2644 else
2645 'SwitchGoToMouseMarkPos 'fGoToMouseMark
2646 endif
2647
2648 if DoubleClickMarks = '?' then
2649 -- nop
2650 else
2651 'SwitchDoubleClickMarks 'DoubleClickMarks
2652 endif
2653
2654 if f4os2MouseMark = '?' then
2655 -- nop
2656 elseif f4os2MouseMark <> Query4os2MouseMark() then
2657 'Toggle4os2MouseMark'
2658 endif
2659
2660 if fDoubleClickUnmarks = '?' then
2661 -- nop
2662 else
2663 'SwitchDoubleClickUnmarks 'fDoubleClickUnmarks
2664 endif
2665
2666 KeyPath = '\NEPMD\User\SearchDialog\SearchMarkIfMarked'
2667 if fSearchMarkIfMarked = '?' then
2668 -- nop
2669 elseif fSearchMarkIfMarked <> QueryConfigKey( KeyPath) then
2670 'toggle_SearchMarkIfMarked'
2671 endif
2672
2673 KeyPath = '\NEPMD\User\SearchDialog\SearchMarkedWords'
2674 if fSearchMarkedWords = '?' then
2675 -- nop
2676 elseif fSearchMarkedWords <> QueryConfigKey( KeyPath) then
2677 'toggle_SearchMarkedWords'
2678 endif
2679
2680 if GetMenuAVar( 'mid_markingsettings') then
2681 'menuinit_markingsettings'
2682 endif
2683 call MH_Set_Mouse()
2684 'ReloadKeyset' -- -> SetKeyset2 -> SwitchKeyset -> RefreshMenu - required for hint text
2685
2686 -- E precision is max. 9 digits, DigitComp is required
2687 if GetMenuAVar( 'mid_advancedmarking') then
2688 SetMenuAttribute( 'advancedmarking', MIA_CHECKED,
2689 DigitComp( CurrentMarkingBitStr, GetDefaultMarkingBitStr( 'ADV')))
2690 endif
2691 if GetMenuAVar( 'mid_cuamarking') then
2692 SetMenuAttribute( 'cuamarking', MIA_CHECKED,
2693 DigitComp( CurrentMarkingBitStr, GetDefaultMarkingBitStr( 'CUA')))
2694 endif
2695
2696 enddo
2697
2698; ---------------------------------------------------------------------------
2699defproc ReplaceMark
2700 do once = 1 to 1
2701 fMarkDeleted = 0
2702
2703 -- Config key
2704 KeyPath = '\NEPMD\User\Mark\ReplaceMark'
2705 fReplaceMark = QueryConfigKey( KeyPath)
2706 if not fReplaceMark then
2707 leave
2708 endif
2709
2710 -- File not marked
2711 if not FileIsMarked() then
2712 if marktype() then
2713 -- Unmark mark in other file
2714 unmark
2715 endif
2716 leave
2717 endif
2718
2719 getmark firstline, lastline, firstcol, lastcol, markfileid
2720 -- Delete mark buffer, see clipbrd.e for details
2721 'Copy2DMBuff'
2722
2723 -- Place cursor and delete mark
2724 firstline
2725 .col = firstcol
2726 call NextCmdAltersText()
2727 call pDelete_Mark()
2728
2729 -- Remove content in EPM shared text buffer
2730 'ClearSharBuff'
2731 fMarkDeleted = 1
2732 enddo
2733 return fMarkDeleted
2734
2735; ---------------------------------------------------------------------------
2736defc SwitchReplaceMark
2737 do once = 1 to 1
2738 KeyPath = '\NEPMD\User\Mark\ReplaceMark'
2739 NewState = upcase( strip( leftstr( arg( 1), 1)))
2740 if NewState = 'T' then
2741 fReplaceMark = QueryConfigKey( KeyPath)
2742 NewState = not fReplaceMark
2743 elseif NewState = 0 then
2744 -- nop
2745 elseif NewState = 1 then
2746 -- nop
2747 else
2748 'SayError SwitchReplaceMark: Undefined arg 'arg( 1)' specified.'
2749 leave
2750 endif
2751 WriteConfigKey( KeyPath, NewState)
2752 if GetMenuAVar( 'mid_replacemark') then
2753 SetMenuAttribute( 'replacemark', MIA_CHECKED, not NewState)
2754 endif
2755 enddo
2756
2757; ---------------------------------------------------------------------------
2758defproc QueryReplaceMark
2759 KeyPath = '\NEPMD\User\Mark\ReplaceMark'
2760 fReplaceMark = QueryConfigKey( KeyPath)
2761 return fReplaceMark
2762
2763; ---------------------------------------------------------------------------
2764defc SwitchDirectMarkActions
2765 do once = 1 to 1
2766 KeyPath = '\NEPMD\User\Mark\DirectMarkActions'
2767 NewState = upcase( strip( leftstr( arg( 1), 1)))
2768 if NewState = 'T' then
2769 fDirectMarkActions = QueryConfigKey( KeyPath)
2770 NewState = not fDirectMarkActions
2771 elseif NewState = 0 then
2772 -- nop
2773 elseif NewState = 1 then
2774 -- nop
2775 else
2776 'SayError SwitchDirectMarkActions: Undefined arg 'arg( 1)' specified.'
2777 leave
2778 endif
2779 WriteConfigKey( KeyPath, NewState)
2780 if GetMenuAVar( 'mid_directmarkactions') then
2781 SetMenuAttribute( 'directmarkactions', MIA_CHECKED, not NewState)
2782 endif
2783 if NewState = 1 then
2784 -- Uncheck 'Unmark on any key'
2785 'SwitchUnmarkOnAnyKey 0'
2786 endif
2787 -- Direct mark menu items (Copy, Move, Overlay, Adjust) are added/removed
2788 'RefreshMenu'
2789 enddo
2790
2791; ---------------------------------------------------------------------------
2792defproc QueryDirectMarkActions
2793 KeyPath = '\NEPMD\User\Mark\DirectMarkActions'
2794 fDirectMarkActions = QueryConfigKey( KeyPath)
2795 return fDirectMarkActions
2796
2797; ---------------------------------------------------------------------------
2798defproc UnmarkOnAnyKey
2799 KeyPath = '\NEPMD\User\Mark\UnmarkOnAnyKey'
2800 fUnmarkOnAnyKey = QueryConfigKey( KeyPath)
2801 if fUnmarkOnAnyKey then
2802 unmark
2803 endif
2804 return fUnmarkOnAnyKey
2805
2806; ---------------------------------------------------------------------------
2807defproc QueryUnmarkOnAnyKey
2808 KeyPath = '\NEPMD\User\Mark\UnmarkOnAnyKey'
2809 fUnmarkOnAnyKey = QueryConfigKey( KeyPath)
2810 return fUnmarkOnAnyKey
2811
2812; ---------------------------------------------------------------------------
2813defc SwitchUnmarkOnAnyKey
2814 do once = 1 to 1
2815 KeyPath = '\NEPMD\User\Mark\UnmarkOnAnyKey'
2816 NewState = upcase( strip( leftstr( arg( 1), 1)))
2817 if NewState = 'T' then
2818 fUnmarkOnAnyKey = QueryConfigKey( KeyPath)
2819 NewState = not fUnmarkOnAnyKey
2820 elseif NewState = 0 then
2821 -- nop
2822 elseif NewState = 1 then
2823 -- nop
2824 else
2825 'SayError SwitchUnmarkOnAnyKey: Undefined arg 'arg( 1)' specified.'
2826 leave
2827 endif
2828 WriteConfigKey( KeyPath, NewState)
2829 if GetMenuAVar( 'mid_unmarkonanykey') then
2830 SetMenuAttribute( 'unmarkonanykey', MIA_CHECKED, not NewState)
2831 endif
2832 if NewState = 1 then
2833 -- Switch 'Direct mark actions' off
2834 'SwitchDirectMarkActions 0'
2835 -- Switch 'Sh-mark always extends' off
2836 'SwitchShiftMarkAlwaysExtends 0'
2837 endif
2838 enddo
2839
2840; ---------------------------------------------------------------------------
2841defc SwitchShiftMarkAlwaysExtends
2842 do once = 1 to 1
2843 KeyPath = '\NEPMD\User\MarkShiftMarkExtends'
2844 NewState = upcase( strip( leftstr( arg( 1), 1)))
2845 if NewState = 'T' then
2846 fShiftMarkAlwaysExtends = QueryConfigKey( KeyPath)
2847 NewState = not fShiftMarkAlwaysExtends
2848 elseif NewState = 0 then
2849 -- nop
2850 elseif NewState = 1 then
2851 -- nop
2852 else
2853 'SayError SwitchShiftMarkAlwaysExtends: Undefined arg 'arg( 1)' specified.'
2854 leave
2855 endif
2856 WriteConfigKey( KeyPath, NewState)
2857 if GetMenuAVar( 'mid_shiftmarkextends') then
2858 SetMenuAttribute( 'shiftmarkextends', MIA_CHECKED, not NewState)
2859 endif
2860 if NewState = 1 then
2861 -- Switch 'Unmark on any key' off
2862 'SwitchUnmarkOnAnyKey 0'
2863 endif
2864 enddo
2865
2866; ---------------------------------------------------------------------------
2867; Moves the cursor to the pos. of the pointer. This is used at the end of
2868; mouse marking. The cursor pos. must be limitted to text pos. or just after
2869; the last column plus line end.
2870defproc GoToMouseMarkPos
2871 do once = 1 to 1
2872 -- This is not active for advanced marking
2873 KeyPath = '\NEPMD\User\Mark\GoToMousePos'
2874 fGoToMousePos = QueryConfigKey( KeyPath)
2875 if not fGoToMousePos then
2876 leave
2877 endif
2878
2879 -- Save horiz. scrolled pels
2880 oldsx = .scrollx
2881
2882 -- Query pointer pos.
2883 call GetPointerPos( MouseLine, MouseCol)
2884 CursorLine = MouseLine
2885 CursorCol = MouseCol
2886
2887 -- Limit CursorLine
2888 if CursorLine < 1 then
2889 KeyPath = '\NEPMD\User\Mark\LineInsert'
2890 LineInsert = QueryConfigKey( KeyPath)
2891 if LineInsert = 'A' then -- above current line
2892 MinCursorLine = 1
2893 else
2894 MinCursorLine = 0
2895 endif
2896 CursorLine = MinCursorLine
2897 endif
2898 if CursorLine > .last then
2899 CursorLine = .last
2900 endif
2901
2902 -- Limit CursorCol
2903 -- If mouse button was released after line end, limit cursor pos.
2904 -- to after line end, like the mark.
2905 CursorLineLen = length( textline( CursorLine))
2906 if CursorCol > CursorLineLen + 2 then
2907 CursorCol = CursorLineLen + 2
2908 endif
2909
2910 -- Set cursor pos.
2911 .lineg = CursorLine -- without scrolling
2912 .col = CursorCol
2913
2914 -- Restore horiz. scrolled pels
2915 .scrollx = oldsx
2916 enddo
2917
2918 return
2919
2920; ---------------------------------------------------------------------------
2921defc SwitchGoToMouseMarkPos
2922 do once = 1 to 1
2923 KeyPath = '\NEPMD\User\Mark\GoToMousePos'
2924 NewState = upcase( strip( leftstr( arg( 1), 1)))
2925 if NewState = 'T' then
2926 fGoToMousePos = QueryConfigKey( KeyPath)
2927 NewState = not fGoToMousePos
2928 elseif NewState = 0 then
2929 -- nop
2930 elseif NewState = 1 then
2931 -- nop
2932 else
2933 'SayError SwitchGoToMouseMarkPos: Undefined arg 'arg( 1)' specified.'
2934 leave
2935 endif
2936 WriteConfigKey( KeyPath, NewState)
2937 if GetMenuAVar( 'mid_gotomousemark') then
2938 SetMenuAttribute( 'gotomousemark', MIA_CHECKED, not NewState)
2939 SetMenuAttribute( 'gotomousemark2', MIA_CHECKED, not NewState)
2940 endif
2941 enddo
2942
2943; ---------------------------------------------------------------------------
2944defproc QueryGoToMouseMarkPos
2945 KeyPath = '\NEPMD\User\Mark\GoToMousePos'
2946 fGoToMouseMarkPos = QueryConfigKey( KeyPath)
2947 return fGoToMouseMarkPos
2948
2949; ---------------------------------------------------------------------------
2950defc SwitchDoubleClickUnmarks
2951 do once = 1 to 1
2952 KeyPath = '\NEPMD\User\MB1DoubleClick\UnmarkOnSpace'
2953 NewState = upcase( strip( leftstr( arg( 1), 1)))
2954 if NewState = 'T' then
2955 fDoubleClickUnmarks = QueryConfigKey( KeyPath)
2956 NewState = not fDoubleClickUnmarks
2957 elseif NewState = 0 then
2958 -- nop
2959 elseif NewState = 1 then
2960 -- nop
2961 else
2962 'SayError SwitchDoubleClickUnmarks: Undefined arg 'arg( 1)' specified.'
2963 leave
2964 endif
2965 WriteConfigKey( KeyPath, NewState)
2966 if GetMenuAVar( 'mid_doubleclickunmarks') then
2967 SetMenuAttribute( 'doubleclickunmarks', MIA_CHECKED, not NewState)
2968 SetMenuAttribute( 'doubleclickunmarks2', MIA_CHECKED, not NewState)
2969 endif
2970 enddo
2971
2972; ---------------------------------------------------------------------------
2973defproc QueryDoubleClickUnmarks
2974 KeyPath = '\NEPMD\User\MB1DoubleClick\UnmarkOnSpace'
2975 fDoubleClickUnmarks = QueryConfigKey( KeyPath)
2976 return fDoubleClickUnmarks
2977
2978; ---------------------------------------------------------------------------
2979defc SwitchDoubleClickMarks
2980 do once = 1 to 1
2981 KeyPath = '\NEPMD\User\MB1DoubleClick\Mark'
2982 NewState = upcase( strip( leftstr( arg( 1), 1)))
2983 if NewState = 'T' then
2984 CurState = upcase( strip( leftstr( QueryConfigKey( KeyPath), 1)))
2985 if CurState = 'W' then
2986 NewState = 'I'
2987 elseif CurState = 'I' then
2988 NewState = 0
2989 else
2990 NewState = 'W'
2991 endif
2992 endif
2993 if NewState = 0 then
2994 Val = 'doesn''t mark'
2995 elseif NewState = 'W' then
2996 Val = 'marks word'
2997 elseif NewState = 'I' then
2998 Val = 'marks identifier'
2999 else
3000 'SayError SwitchDoubleClickMarks: Undefined arg 'arg( 1)' specified.'
3001 leave
3002 endif
3003 WriteConfigKey( KeyPath, NewState)
3004 if GetMenuAVar( 'mid_doubleclickmarks') then
3005 SetMenuVarText( 'doubleclickmarks', Val)
3006 SetMenuVarText( 'doubleclickmarks2', Val)
3007 endif
3008 enddo
3009
3010; ---------------------------------------------------------------------------
3011defproc QueryDoubleClickMarks
3012 KeyPath = '\NEPMD\User\MB1DoubleClick\Mark'
3013 DoubleClickMarks = QueryConfigKey( KeyPath)
3014 return DoubleClickMarks
3015
3016; ---------------------------------------------------------------------------
3017defproc QueryDoubleClickOpensUrl
3018 KeyPath = '\NEPMD\User\MB1DoubleClick\OpenUrl'
3019 DoubleClickOpensUrl = QueryConfigKey( KeyPath)
3020 return DoubleClickOpensUrl
3021
3022; ---------------------------------------------------------------------------
3023defproc QueryDoubleClickDirOpensFile
3024 KeyPath = '\NEPMD\User\MB1DoubleClick\DirOpenFile'
3025 DoubleClickDirOpensFile = QueryConfigKey( KeyPath)
3026 return DoubleClickDirOpensFile
3027
3028; ---------------------------------------------------------------------------
3029defc SwitchDefaultMouseMark
3030 do once = 1 to 1
3031 KeyPath = '\NEPMD\User\Mark\DefaultMouseMark'
3032 NewState = upcase( strip( leftstr( arg( 1), 1)))
3033 if NewState = 'T' then
3034 DefaultMouseMark = QueryConfigKey( KeyPath)
3035 if DefaultMouseMark = 'B' then -- toggle
3036 DefaultMouseMark = 'C'
3037 new = 'char'
3038 else
3039 DefaultMouseMark = 'B'
3040 new = 'block'
3041 endif
3042 elseif NewState = 'B' then
3043 DefaultMouseMark = 'B'
3044 new = 'block'
3045 elseif NewState = 'C' then
3046 DefaultMouseMark = 'C'
3047 new = 'char'
3048 else
3049 'SayError SwitchReplaceMark: Undefined arg 'arg( 1)' specified.'
3050 leave
3051 endif
3052 WriteConfigKey( KeyPath, DefaultMouseMark)
3053 if GetMenuAVar( 'mid_defaultmousemark') then
3054 SetMenuVarText( 'defaultmousemark', new)
3055 SetMenuVarText( 'defaultmousemark2', new)
3056 endif
3057 call MH_Set_Mouse()
3058 enddo
3059
3060; ---------------------------------------------------------------------------
3061defproc DoubleClickMarksWord
3062 do once = 1 to 1
3063 if not .line then
3064 leave
3065 endif
3066
3067 -- Config key
3068 KeyPath = '\NEPMD\User\MB1DoubleClick\MarkWord'
3069 fMarkWord = QueryConfigKey( KeyPath)
3070 if not fMarkWord then
3071 leave
3072 endif
3073
3074 fMouseAfterLine = 0
3075 -- Won't position cursor after line end in stream mode
3076 'MH_GoToLastClick'
3077 MouseCol = .col
3078 endline
3079 if .col <= MouseCol then
3080 fMouseAfterLine = 1
3081 endif
3082
3083 if fMouseAfterLine then
3084 -- Mark only line end
3085 endline
3086 getfileid fid
3087 call pSet_Mark( .line, .line, .col, .col + 1, 'CHAR', fid)
3088 else
3089 --call pMark_Word()
3090 -- pMark_Word doesn't include white space; the following does:
3091 call pBegin_Word()
3092 KeyPath = '\NEPMD\User\Mark\WordMarkType'
3093 WordMarkType = QueryConfigKey( KeyPath)
3094 if WordMarkType = 'B' then
3095 markblock
3096 else
3097 markchar
3098 endif
3099 startcol = .col
3100 tabword
3101 .col = .col - 1
3102 if WordMarkType = 'B' then
3103 markblock
3104 else
3105 markchar
3106 endif
3107 .col = startcol
3108 endif
3109
3110 -- Copy mark to shared text buffer
3111 'Copy2SharBuff'
3112 'MatchFindOnMove'
3113 enddo
3114 return
3115
3116; ---------------------------------------------------------------------------
3117defc ConfigureNewlineCmd
3118 universal newline_enter
3119 universal default_stream_mode
3120
3121 -- Menu item name
3122 miname = arg( 1)
3123 if miname = '' then
3124 miname = 'newline'
3125 endif
3126 key = lowcase( miname)
3127 if newline_enter = 'enter' then
3128 key = ChangeStr( 'newline', key, 'enter')
3129 endif
3130
3131 KeyPath = '\NEPMD\User\SpecialKeys'
3132 if default_stream_mode then
3133 KeyPath = KeyPath'\Stream'
3134 else
3135 KeyPath = KeyPath'\Line'
3136 endif
3137 KeyPath = KeyPath'\'key
3138 next = QueryConfigKey( KeyPath)
3139 if next = '' then
3140 next = 'Split,KeepIndent'
3141 endif
3142 parse value next with SplitCfg','ColCfg','fCmd','Cmd
3143
3144 Title = 'Configure command for 'key
3145 Text = 'Enter an E command:'
3146 Text = Text''copies( ' ', Max( 100 - length(Text), 0))
3147 Buttons = '/~Set/~Reset/'CANCEL__MSG
3148 Entry = Cmd
3149 if rightstr( Entry, 2) <> ':\' then
3150 Entry = strip( Entry, 'T', '\')
3151 endif
3152 parse value EntryBox( Title,
3153 Buttons,
3154 Entry,
3155 '',
3156 '',
3157 atoi( 1) || atoi( 0) || atol( 0) ||
3158 Text) with button 2 Cmd \0
3159 Cmd = strip( Cmd)
3160 if button = \1 then -- Set
3161 -- nop
3162 elseif button = \2 then -- Reset
3163 Cmd = ''
3164 else -- Cancel
3165 return
3166 endif
3167
3168 fCmd = 1
3169 Val = SplitCfg','ColCfg','fCmd','Cmd
3170 WriteConfigKey( KeyPath, Val)
3171 MenuText_newlinesplit( key)
3172
3173; ---------------------------------------------------------------------------
3174defproc GetExpandKeys
3175 KeyPath = '\NEPMD\User\SpecialKeys\ExpandKeys'
3176 ExpandKeys = QueryConfigKey( KeyPath, 'space newline')
3177 return ExpandKeys
3178
3179; ---------------------------------------------------------------------------
3180defproc SetExpandKeys
3181 KeyPath = '\NEPMD\User\SpecialKeys\ExpandKeys'
3182 NewExpandKeys = arg( 1)
3183 if NewExpandKeys <> '' then
3184 call WriteConfigKey( KeyPath, NewExpandKeys)
3185 else
3186 call DeleteConfigKey( KeyPath)
3187 endif
3188 if isadefproc( 'MenuText_syntaxexpansionkeys') then
3189 MenuText_syntaxexpansionkeys()
3190 endif
3191
3192; ---------------------------------------------------------------------------
3193defc SelectExpandKeys
3194 universal nodismiss
3195
3196 CurExpandKeys = GetExpandKeys()
3197
3198 Title = 'Configure syntax expansion keys'
3199 Text = 'Specify e.g. "space newline" or "c_space c_newline":'
3200 Text = Text''copies( ' ', Max( 100 - length( Text), 0))
3201 Buttons = '/~Set/~Reset/'CANCEL__MSG
3202 Entry = CurExpandKeys
3203 parse value EntryBox( Title,
3204 Buttons,
3205 Entry,
3206 '',
3207 '',
3208 atoi( 1) || atoi( 0) || atol( 0) ||
3209 Text) with button 2 NewExpandKeys \0
3210 NewExpandKeys = strip( NewExpandKeys)
3211 if button = \1 then -- Set
3212 -- nop
3213 elseif button = \2 then -- Reset
3214 NewExpandKeys = ''
3215 else -- Cancel
3216 return
3217 endif
3218
3219 if NewExpandKeys <> CurExpandKeys then
3220 call SetExpandKeys( NewExpandKeys)
3221 else
3222 'SayError Syntax expansion keys not changed.'
3223 endif
3224
3225; ---------------------------------------------------------------------------
3226defproc ExpandSyntax()
3227 universal curkey
3228--dprintf( 'ExpandSyntax: curkey = 'curkey)
3229
3230 KeyPath = '\NEPMD\User\SpecialKeys\ExpandKeys'
3231 CurExpandKeys = QueryConfigKey( KeyPath, 'space newline')
3232 fExpanded = 0
3233 parse value curkey with KeyString \1 Cmd
3234 wp = wordpos( KeyString, CurExpandKeys)
3235 if wp = 1 then
3236 fExpanded = ExpandFirstSecond( 0)
3237 elseif wp = 2 then
3238 fExpanded = ExpandFirstSecond( 1)
3239 endif
3240 return fExpanded
3241
3242; ---------------------------------------------------------------------------
3243; Process syntax expansion.
3244defproc ExpandFirstSecond( fSecond)
3245 universal expand_on
3246
3247 fExpanded = 0
3248 ExpandMode = GetFileAVar( 'expandmode')
3249 --dprintf( 'ExpandFirstSecond( 'fSecond'): expand_on = 'expand_on', ExpandMode = 'ExpandMode)
3250 do once = 1 to 1
3251 if not expand_on then
3252 leave
3253 endif
3254 if ExpandMode = '' then
3255 leave
3256 endif
3257 if wordpos( upcase( ExpandMode), '0 OFF') > 0 then
3258 leave
3259 endif
3260
3261 if fSecond then
3262 ExpandCmd = ExpandMode'SecondExpansion'
3263 else
3264 ExpandCmd = ExpandMode'FirstExpansion'
3265 endif
3266 if isadefc( ExpandCmd) then
3267 ExpandCmd
3268 fExpanded = (rc == 0)
3269 endif
3270 enddo
3271 return fExpanded
3272
3273; ---------------------------------------------------------------------------
3274; rc = 0 after expansion, otherwise rc = 1
3275defc ForceExpansion
3276 universal expand_on
3277
3278 fExpanded = 0
3279 ExpandMode = GetFileAVar( 'expandmode')
3280 do once = 1 to 1
3281 if not expand_on then
3282 leave
3283 endif
3284 if ExpandMode = '' then
3285 leave
3286 endif
3287 if wordpos( upcase( ExpandMode), '0 OFF') > 0 then
3288 leave
3289 endif
3290
3291 rc = -1
3292 if isadefc( ExpandMode'FirstExpansion') then
3293 ExpandMode'FirstExpansion force'
3294 endif
3295 if rc <> 0 then
3296 if isadefc( ExpandMode'SecondExpansion') then
3297 ExpandMode'SecondExpansion force'
3298 endif
3299 endif
3300 fExpanded = (rc == 0)
3301 enddo
3302 rc = (fExpanded == 0) -- rc = 1 means: not expanded
3303
3304; ---------------------------------------------------------------------------
3305defc HeaderWidthDlg
3306 universal header_width
3307
3308 KeyPath = '\NEPMD\User\Format\HeaderWidth'
3309 NewHeaderWidth = arg( 1)
3310 if NewHeaderWidth <> '' then
3311 if IsUInt( NewHeaderWidth) then
3312 call WriteConfigKey( KeyPath, NewHeaderWidth)
3313 header_width = NewHeaderWidth
3314 return
3315 elseif upcase( NewHeaderWidth) = 'RESET' then
3316 call DeleteConfigKey( KeyPath)
3317 header_width = QueryConfigKey( KeyPath)
3318 return
3319 endif
3320 endif
3321
3322 Title = 'Set header width'
3323 Text = 'Number of columns used for boxes, center, wrap and syntax expansion:'
3324 Text = Text''copies( ' ', Max( 100 - length( Text), 0))
3325 Buttons = '/~Set/~Reset/'CANCEL__MSG
3326 Entry = header_width
3327 parse value EntryBox( Title,
3328 Buttons,
3329 Entry,
3330 0,
3331 240,
3332 atoi( 1) || atoi( 0) || atol( 0) ||
3333 Text) with Button 2 NewHeaderWidth \0
3334 NewHeaderWidth = strip( NewHeaderWidth)
3335 if Button = \1 then -- Set
3336 -- nop
3337 elseif Button = \2 then -- Reset
3338 NewHeaderWidth = ''
3339 else -- Cancel
3340 return
3341 endif
3342
3343 if NewHeaderWidth <> header_width & IsUInt( NewHeaderWidth) then
3344 'HeaderWidthDlg' NewHeaderWidth
3345 else
3346 'HeaderWidthDlg RESET'
3347 endif
3348
3349; ---------------------------------------------------------------------------
3350; Syntax:
3351; FoundLineNum =
3352; WordWithIndentExists( Wrd, IndentLen [, Case [, MaxLines]])
3353; Case = 0 means caseless, the default value is 1 (case-sensitive).
3354; Finds e.g. 'endddo' in next lines with the same indent. Stops at max.
3355; processed lines. Stops if indent is lower. Recognizes comments and
3356; literals. Handles tabs correctly.
3357; This is used by syntax expansion procs.
3358; IndentLen is the length of the blank area after expanding tabs.
3359; Return the found line number. If Wrd is not found, 0 is returned.
3360defproc WordWithIndentExists( Wrd, IndentLen)
3361 Case = arg( 3)
3362 if Case <> 0 then
3363 Case = 1 -- case-sensitive
3364 endif
3365 MaxLines = arg( 4)
3366 if MaxLines = '' then
3367 MaxLines = 100
3368 endif
3369 CurMode = GetMode()
3370
3371 -- Search in comments if the Wrd to search is a comment char itself
3372 fSearchInComments = 0
3373 CommentChars = QueryModeKey( CurMode, 'LineComment')
3374 CommentChars = CommentChars' 'QueryModeKey( CurMode, 'MultiLineCommentStart')
3375 CommentChars = CommentChars' 'QueryModeKey( CurMode, 'MultiLineCommentEnd')
3376 if wordpos( Wrd, CommentChars) then
3377 fSearchInComments = 1
3378 endif
3379
3380 FoundLineNum = 0
3381 --dprintf( 'KeyWord = 'KeyWord', IndentLen = 'IndentLen' ------')
3382 l = .line
3383 do forever
3384 l = l + 1
3385 if l > .last then
3386 leave
3387 endif
3388 if l - .line > MaxLines then
3389 leave
3390 endif
3391
3392 getline NextLineStr, l
3393 NextFirstWrd = word( translate( NextLineStr, ' ', \9), 1)
3394 UpNextFirstWrd = upcase( NextFirstWrd)
3395 pNextFirstWrd = pos( UpNextFirstWrd, upcase( NextLineStr))
3396 NextSpc = leftstr( NextLineStr, Max( 0, pNextFirstWrd - 1)) -- Indent of line with tabs and spaces
3397 NextExpSpc = TabExpandStr( NextSpc, TabWidth, junk)
3398 NextExpSpcLen = length( NextExpSpc)
3399 --InComment = InsideCommentLiteral( GetMode(), l, pNextFirstWrd)
3400 --dprintf( rightstr( l, 2)': NextFirstWrd = 'NextFirstWrd', pNextFirstWrd = 'pNextFirstWrd', NextExpSpcLen = 'NextExpSpcLen', InComment = 'InComment', fSearchInComments = 'fSearchInComments)
3401
3402 if NextFirstWrd = '' then
3403 iterate
3404 elseif not fSearchInComments & InsideCommentLiteral( CurMode, l, pNextFirstWrd) then
3405 iterate
3406 elseif NextExpSpcLen < IndentLen then
3407 leave
3408 elseif NextExpSpcLen > IndentLen then
3409 iterate
3410 else
3411 if Case = 1 then
3412 if NextFirstWrd = Wrd then
3413 FoundLineNum = l
3414 leave
3415 endif
3416 else
3417 if UpNextFirstWrd = upcase( Wrd) then
3418 FoundLineNum = l
3419 leave
3420 endif
3421 endif
3422 endif
3423 enddo
3424 return FoundLineNum
3425
3426; ---------------------------------------------------------------------------
3427defc Space
3428 call NextCmdAltersText( 'S')
3429 call Process_Key( ' ')
3430
3431; ---------------------------------------------------------------------------
3432defc AdjustMark
3433 call NextCmdAltersText()
3434 call pCommon_Adjust_Overlay( 'A')
3435
3436; ---------------------------------------------------------------------------
3437defc OverlayMark
3438 call NextCmdAltersText()
3439 if marktype() then
3440 call pCommon_Adjust_Overlay( 'O')
3441 else -- If no mark, look into shared text buffer
3442 'GetSharBuff O'
3443 endif
3444
3445; ---------------------------------------------------------------------------
3446defc CopyMark
3447 universal stream_mode
3448
3449 -- This creates only a new state if required, not when just the mark
3450 -- has changed
3451 call NextCmdAltersText()
3452
3453 -- Ensure that cursor is on a line > 0
3454 if .line = 0 then
3455 -- Not for insert below
3456 KeyPath = '\NEPMD\User\Mark\LineInsert'
3457 LineInsert = QueryConfigKey( KeyPath)
3458 if LineInsert = 'A' then
3459 if .last = 0 then
3460 insertline '', 1
3461 endif
3462 down
3463 endif
3464 -- Not for line mode
3465 if stream_mode then
3466 .col = 1
3467 endif
3468 endif
3469
3470 if marktype() then
3471 -- Ensure that pos and mark before the action is saved
3472 getfileid fid
3473 StateRange = QueryUndoState()
3474 parse value StateRange with OldestState NewestState
3475 -- Eventually override the previously saved pos and mark
3476 call SetUndoStatePos( fid, NewestState)
3477
3478 call pCopy_Mark()
3479 else
3480 -- If no mark, look into shared text buffer
3481 'GetSharBuff'
3482 endif
3483
3484; ---------------------------------------------------------------------------
3485defc MoveMark
3486 universal stream_mode
3487
3488 -- This creates only a new state if required, not when just the mark
3489 -- has changed
3490 call NextCmdAltersText()
3491
3492 -- Ensure that cursor is on a line > 0
3493 if .line = 0 then
3494 -- Not for insert below
3495 KeyPath = '\NEPMD\User\Mark\LineInsert'
3496 LineInsert = QueryConfigKey( KeyPath)
3497 if LineInsert = 'A' then
3498 if .last = 0 then
3499 insertline '', 1
3500 endif
3501 down
3502 endif
3503 -- Not for line mode
3504 if stream_mode then
3505 .col = 1
3506 endif
3507 endif
3508
3509 -- Ensure that pos and mark before the action is saved
3510 getfileid fid
3511 StateRange = QueryUndoState()
3512 parse value StateRange with OldestState NewestState
3513 -- Eventually override the previously saved pos and mark
3514 call SetUndoStatePos( fid, NewestState)
3515
3516 call pMove_Mark()
3517 KeyPath = '\NEPMD\User\Mark\UnmarkAfterMove'
3518 UnmarkAfterMove = QueryConfigKey( KeyPath)
3519 if UnmarkAfterMove = 1 then
3520 unmark
3521 -- Remove content in shared text buffer
3522 'ClearSharBuff'
3523 endif
3524
3525; ---------------------------------------------------------------------------
3526defc DeleteMark
3527 getmark firstline, lastline, firstcol, lastcol, markfileid
3528 MkType = marktype()
3529 getfileid fileid
3530 if fileid <> markfileid then
3531 'SayError 'MARKED_OTHER__MSG
3532 unmark
3533 endif
3534 -- Position cursor if it was on a marked line
3535 if .line >= firstline & .line <= lastline then
3536 if MkType = 'CHAR' & .line = firstline & .col <= firstcol then
3537 -- nop
3538 elseif MkType = 'BLOCK' & .col <= firstcol then
3539 -- nop
3540 elseif MkType = 'CHAR' | MkType = 'LINE' then
3541 firstline
3542 .col = firstcol
3543 elseif MkType = 'BLOCK' then
3544 .col = firstcol
3545 endif
3546 endif
3547 call NextCmdAltersText()
3548 -- Ensure that pos and mark before the action is saved
3549 getfileid fid
3550 StateRange = QueryUndoState()
3551 parse value StateRange with OldestState NewestState
3552 -- Eventually override the previously saved pos and mark
3553 call SetUndoStatePos( fid, NewestState)
3554
3555 'Copy2DMBuff'
3556 call pDelete_Mark()
3557 'ClearSharBuff' -- Remove content in shared text buffer
3558
3559; ---------------------------------------------------------------------------
3560defc Unmark
3561 unmark
3562 'ClearSharBuff' -- Remove content in shared text buffer
3563
3564; ---------------------------------------------------------------------------
3565defc BeginMark
3566 mt = leftstr( marktype(), 1)
3567 if mt then
3568 getmark firstline, lastline, firstcol, lastcol, fileid
3569 activatefile fileid
3570 fMarkedLineOnScreen = OnScreen( firstline)
3571
3572 call pBegin_Mark()
3573 if mt = 'L' then
3574 .col = 1
3575 endif
3576 -- Ensure that the cursor is within the window area
3577 if not fMarkedLineOnScreen then
3578 'CenterLine'
3579 endif
3580 else
3581 'SayError 'NO_MARK_HERE__MSG
3582 endif
3583
3584; ---------------------------------------------------------------------------
3585defc EndMark
3586 mt = leftstr( marktype(), 1)
3587 if mt then
3588 getmark firstline, lastline, firstcol, lastcol, fileid
3589 activatefile fileid
3590 fMarkedLineOnScreen = OnScreen( lastline)
3591
3592 call pEnd_Mark()
3593 if mt = 'L' then
3594 endline
3595 elseif mt = 'C' then
3596 getmark firstline, lastline, firstcol, lastcol, fileid
3597 if lastcol = 0 then
3598 .lineg = lastline - 1
3599 endline
3600 endif
3601 endif
3602 -- Ensure that the cursor is within the window area
3603 if not fMarkedLineOnScreen then
3604 'CenterLine'
3605 endif
3606 else
3607 'SayError 'NO_MARK_HERE__MSG
3608 endif
3609
3610; ---------------------------------------------------------------------------
3611defc AfterMark
3612 mt = leftstr( marktype(), 1)
3613 if mt then
3614 getmark firstline, lastline, firstcol, lastcol, fileid
3615 activatefile fileid
3616 fMarkedLineOnScreen = OnScreen( lastline)
3617 LastLineStr = textline( lastline)
3618 LastLineLen = length( lastline)
3619
3620 if mt = 'L' then
3621 .lineg = lastline + 1
3622 .col = 1
3623 elseif mt = 'B' then
3624 .lineg = lastline
3625 .col = lastcol + 1
3626 elseif mt = 'C' then
3627 if lastcol = 0 then
3628 .lineg = lastline
3629 .col = 1
3630 elseif lastcol = LastLineLen + 1 then
3631 .lineg = lastline + 1
3632 .col = 1
3633 else
3634 .lineg = lastline
3635 .col = lastcol + 1
3636 endif
3637 endif
3638 -- Ensure that the cursor is within the window area
3639 if not fMarkedLineOnScreen then
3640 'CenterLine'
3641 endif
3642 else
3643 'SayError 'NO_MARK_HERE__MSG
3644 endif
3645
3646; ---------------------------------------------------------------------------
3647; This is a callback command used by drag & drop of a marked area.
3648defc DupMark
3649 Type = upcase( arg( 1))
3650 if Type = 'M' then -- M = move
3651 call NextCmdAltersText()
3652 call pMove_Mark()
3653 elseif Type = 'C' then -- C = copy
3654 call NextCmdAltersText()
3655 if marktype() then
3656 call pCopy_Mark()
3657 else -- If no mark, look into shared text buffer
3658 'GetSharBuff'
3659 endif
3660 elseif Type = 'O' then -- O = overlay
3661 call NextCmdAltersText()
3662 if marktype() then
3663 call pCommon_Adjust_Overlay( 'O')
3664 else -- If no mark, look into shared text buffer
3665 'GetSharBuff O'
3666 endif
3667 elseif Type = 'A' then -- A = adjust
3668 call NextCmdAltersText()
3669 call pCommon_Adjust_Overlay( 'A')
3670 elseif Type = 'U' then -- U = unmark
3671 unmark
3672 'ClearSharBuff'
3673 elseif Type = 'U2' then -- U2 = unmark w/o clearing buffer, for drag/drop
3674 unmark
3675 elseif Type = 'D' then -- D = delete mark
3676 'Copy2DMBuff' -- DMBuff = delete-mark buffer
3677 call NextCmdAltersText()
3678 call pDelete_Mark()
3679 'ClearSharBuff'
3680 elseif Type = 'D2' then -- D2 = delete mark w/o touching buffers, for drag/drop
3681 call NextCmdAltersText()
3682 call pDelete_Mark()
3683 elseif Type = 'P' then -- P = print marked area
3684 call CheckMark() -- verify there is a marked area,
3685 'Print' -- then print it.
3686 endif
3687
3688; ---------------------------------------------------------------------------
3689defc TypeFrameChars
3690 call NextCmdAltersText()
3691 call Process_Keys( Ì É È Ê Í Ë Œ » ¹ Î ³ Ã Ú À Á Ä Â Ù ¿ Ž Å Û ² ± °')
3692
3693; ---------------------------------------------------------------------------
3694defc ShiftLeft
3695 MkType = marktype()
3696 if not MkType then
3697 return
3698 endif
3699 getmark firstline, lastline, firstcol, lastcol, fid
3700 getfileid curfid
3701 if curfid <> fid then
3702 unmark
3703 'SayError 'MARKED_OTHER__MSG
3704 return
3705 endif
3706
3707 call NextCmdAltersText()
3708 if MkType = 'CHAR' then
3709 -- Change to line mark
3710 if lastCol = 0 then
3711 lastLine = lastLine - 1
3712 endif
3713 firstcol = 1
3714 lastcol = MAXCOL
3715 unmark
3716 call pSet_Mark( firstline, lastline, firstcol, lastcol, 'LINE', fid)
3717 endif
3718
3719 -- Get minimum indent of current block
3720 if MkType = 'BLOCK' then
3721 pStart = firstcol
3722 else
3723 pStart = 1
3724 endif
3725 MinIndent = MAXCOL
3726 do l = firstline to lastline
3727 getline LineStr, l
3728 LineStr = substr( LineStr, pStart)
3729 CurIndent = Max( 1, verify( LineStr, ' '\t)) - 1
3730 -- Don't count indent of empty lines
3731 if substr( LineStr, CurIndent + 1) = '' then
3732 iterate
3733 endif
3734 if CurIndent < MinIndent then
3735 MinIndent = CurIndent
3736 endif
3737 enddo
3738 -- Don't delete chars at the left
3739 if MinIndent < 1 then
3740 return
3741 endif
3742
3743 shift_left
3744
3745 if marktype() = 'BLOCK' then -- code by Bob Langer
3746 KeyPath = '\NEPMD\User\Mark\ShiftBlockOnly'
3747 fShiftBlockOnly = QueryConfigKey( KeyPath)
3748 -- If fShiftBlockOnly, then the part after the block is fix,
3749 -- otherwise it will be moved with the block, which is the default.
3750 if fShiftBlockOnly then
3751 getmark fl, ll, fc, lc, fid
3752 call pSet_Mark( fl, ll, lc, MAXCOL, 'BLOCK', fid)
3753 shift_right
3754 call pSet_Mark( fl, ll, fc, lc, 'BLOCK', fid)
3755 endif
3756 endif
3757
3758; ---------------------------------------------------------------------------
3759defc ShiftRight
3760 MkType = marktype()
3761 if not MkType then
3762 return
3763 endif
3764 getmark firstline, lastline, firstcol, lastcol, fid
3765 getfileid curfid
3766 if curfid <> fid then
3767 unmark
3768 'SayError 'MARKED_OTHER__MSG
3769 return
3770 endif
3771
3772 call NextCmdAltersText()
3773 if MkType = 'CHAR' then
3774 -- Change to line mark
3775 if lastCol = 0 then
3776 lastLine = lastLine - 1
3777 endif
3778 firstcol = 1
3779 lastcol = MAXCOL
3780 unmark
3781 call pSet_Mark( firstline, lastline, firstcol, lastcol, 'LINE', fid)
3782 endif
3783
3784 -- Get maximum space after last word in all lines within current block
3785 if MkType = 'BLOCK' then
3786 pEnd = lastcol - 1
3787 MinSpace = MAXCOL
3788 do l = firstline to lastline
3789 getline LineStr, l
3790 LineStr = substr( LineStr, firstcol, lastcol - firstcol + 1)
3791 LineStr = translate( LineStr, ' ', \t)
3792 StrippedLineStr = strip( LineStr, 'T')
3793 CurSpace = length( LineStr) - length( StrippedLineStr)
3794 if CurSpace < MinSpace then
3795 MinSpace = CurSpace
3796 endif
3797 enddo
3798 -- Don't delete chars at the right
3799 if MinSpace < 1 then
3800 return
3801 endif
3802 endif
3803
3804 if marktype() = 'BLOCK' then -- code by Bob Langer
3805 KeyPath = '\NEPMD\User\Mark\ShiftBlockOnly'
3806 fShiftBlockOnly = QueryConfigKey( KeyPath)
3807 -- If fShiftBlockOnly, then the part after the block is fix,
3808 -- otherwise it will be moved with the block, which is the default.
3809 if fShiftBlockOnly then
3810 getmark fl, ll, fc, lc, fid
3811 call pSet_Mark( fl, ll, lc, MAXCOL, 'BLOCK', fid)
3812 shift_left
3813 call pSet_Mark( fl, ll, fc, lc, 'BLOCK', fid)
3814 endif
3815 endif
3816
3817 shift_right
3818
3819; ---------------------------------------------------------------------------
3820defc JoinLines
3821 call NextCmdAltersText()
3822 call JoinLines()
3823 'MatchFindOnMove'
3824
3825; ---------------------------------------------------------------------------
3826defc MarkBlock
3827 getmark firstline, lastline, firstcol, lastcol, markfileid
3828 getfileid fileid
3829 if fileid <> markfileid then
3830 unmark
3831 endif
3832 if wordpos( marktype(), 'LINE CHAR') then
3833 --call pset_mark( firstline, lastline, firstcol, lastcol, BLOCKGMARK, fileid)
3834 unmark
3835 endif
3836 markblock
3837 'Copy2SharBuff' -- Copy mark to shared text buffer
3838
3839; ---------------------------------------------------------------------------
3840defc MarkLine
3841 getmark firstline, lastline, firstcol, lastcol, markfileid
3842 getfileid fileid
3843 if fileid <> markfileid then
3844 unmark
3845 endif
3846 if wordpos( marktype(), 'BLOCK CHAR') then
3847 --call pset_mark( firstline, lastline, firstcol, lastcol, LINEMARK, fileid)
3848 unmark
3849 endif
3850 mark_line
3851 'Copy2SharBuff' -- Copy mark to shared text buffer
3852
3853; ---------------------------------------------------------------------------
3854defc MarkChar
3855 getmark firstline, lastline, firstcol, lastcol, markfileid
3856 getfileid fileid
3857 if fileid <> markfileid then
3858 unmark
3859 endif
3860 if wordpos( marktype(), 'BLOCK LINE') then
3861 --call pset_mark( firstline, lastline, firstcol, lastcol, CHARGMARK, fileid)
3862 unmark
3863 endif
3864 mark_char
3865 'Copy2SharBuff' -- Copy mark to shared text buffer
3866
3867; ---------------------------------------------------------------------------
3868defc ShowCursor
3869 if not OnScreen() then
3870 'CenterLine'
3871 endif
3872
3873 -- Set focus to client
3874 -- EPM bug:
3875 -- On dismissing a popup menu, the focus is often not set back to the edit
3876 -- window. Click into it first. Focus switching was also addded to
3877 -- ShowCursor (Ctrl+.) and ProcessEscape (Esc).
3878 'SetFocusToEditClient'
3879
3880 'PostMe HighlightCursor 1'
3881
3882; ---------------------------------------------------------------------------
3883defc HighlightCursor
3884 universal lastcommand
3885
3886 on = arg( 1)
3887 if not wordpos( on, '0 1') then
3888 KeyPath = '\NEPMD\User\CursorPos\HighlightCursor'
3889 on = QueryConfigKey( KeyPath)
3890 endif
3891
3892 if on = 1 then
3893 circleit 5, .line, .col - 1, .col + 1, 16777220
3894 lastcommand = 'highlightcursor'
3895 endif
3896
3897; ---------------------------------------------------------------------------
3898defc TypeFileName -- Type the full name of the current file
3899 call NextCmdAltersText()
3900 call Process_Keys( .filename)
3901
3902; ---------------------------------------------------------------------------
3903defc TypeDateTime -- Type the current date and time
3904 call NextCmdAltersText()
3905 call Process_Keys( DateTime())
3906
3907; ---------------------------------------------------------------------------
3908defc Select_All, SelectAll
3909 getfileid fid
3910 call pSet_Mark( 1, .last, 1, length( textline( .last)), 'CHAR' , fid)
3911 'Copy2SharBuff' -- Copy mark to shared text buffer
3912
3913; ---------------------------------------------------------------------------
3914defproc ReflowGetAvailableModes
3915 Available = ''
3916 ModeList = NepmdQueryModeList()
3917 do w = 1 to words( ModeList)
3918 ThisMode = word( ModeList, w)
3919 if ThisMode = 'TEXT' then
3920 if length( Available) > 0 then
3921 Available = Available' '
3922 endif
3923 Available = Available''ThisMode
3924 elseif isadefc( 'Reflow'ThisMode) then
3925 if length( Available) > 0 then
3926 Available = Available' '
3927 endif
3928 Available = Available''ThisMode
3929 endif
3930 enddo
3931 return Available
3932
3933; ---------------------------------------------------------------------------
3934; This suffices to add a mode to the reflow list:
3935; Reflow menu items in newmenu should also be defined for a new mode.
3936; Extend menuinit_Reflow and optionally ReflowMenuCmd. ReflowMenuCmd executes
3937; Reflow<selectedmode> if not otherwise defined.
3938defc ReflowCONFIGSYS
3939 'SplitPathLines'
3940
3941; ---------------------------------------------------------------------------
3942; Splits CONFIGSYS path lines at ';' or at '+'.
3943defc SplitPathLines
3944 l = 0
3945 NumSplitDirs = 0
3946 SplitWords = '; +'
3947 SavedModify = .modify
3948 SavedAutoSave = .autosave
3949 .autosave = 0
3950 do forever
3951 l = l + 1
3952 if l > .last then
3953 leave
3954 endif
3955 getline LineStr, l
3956
3957 do w = 1 to words( SplitWords)
3958 SplitWord = word( SplitWords, w)
3959 NumSplitWord = count( SplitWord, LineStr)
3960 if NumSplitWord >= 2 then
3961 parse value LineStr with VarName'='ValueStr
3962 if ValueStr = '' then
3963 leave
3964 endif
3965 replaceline VarName'=', l
3966 rest = ValueStr
3967
3968 NumDirs = 0
3969 do while rest <> ''
3970 PrevRest = rest
3971 -- Parse at SplitWord
3972 parse value rest with ThisDir(SplitWord)rest
3973 -- Append SplitWord if in the original
3974 p = pos( SplitWord, PrevRest)
3975 if p = length( ThisDir) + 1 then
3976 ThisDir = ThisDir''SplitWord
3977 endif
3978 -- Insert ThisDir
3979 NumDirs = NumDirs + 1
3980 insertline ' 'ThisDir, l + NumDirs
3981 enddo
3982 l = l + NumDirs
3983 NumSplitDirs = NumSplitDirs + NumDirs
3984
3985 endif
3986
3987 if l = .last then
3988 leave
3989 else
3990 iterate
3991 endif
3992 enddo
3993 enddo
3994
3995 if NumSplitDirs then
3996 'SayError Split 'NumSplitDirs' dirs. Lines will be reconcatenated on Save.'
3997 .modify = SavedModify
3998 -- Save split state
3999 SetFileAVar( 'splitpathlines', 1)
4000 else
4001 'SayError No line split.'
4002 .modify = SavedModify
4003 endif
4004 .autosave = SavedAutoSave
4005
4006; ---------------------------------------------------------------------------
4007; Joins CONFIGSYS path lines. It stops joining if next line is empty,
4008; has no '=' char or has 'REM ' prepended.
4009; This is executed for files of mode CONFIGSYS on Save.
4010defc JoinPathLines
4011 do once = 1 to 1
4012 -- Ensure to process this only when split before
4013 fLinesSplitBefore = (GetFileAVar( 'splitpathlines'))
4014 if not fLinesSplitBefore then
4015 leave
4016 endif
4017
4018 l = 1
4019 SavedAutoSave = .autosave
4020 .autosave = 0
4021 do forever
4022 if l = .last then
4023 leave
4024 endif
4025
4026 getline LineStr, l
4027 getline NextLineStr, l + 1
4028
4029 if LineStr = '' then
4030 l = l + 1
4031 iterate
4032 elseif NextLineStr = '' then
4033 l = l + 1
4034 iterate
4035 elseif pos( '=', NextLineStr) then
4036 l = l + 1
4037 iterate
4038 elseif wordpos( 'REM', upcase( NextLineStr)) = 1 then
4039 l = l + 1
4040 iterate
4041 else
4042 -- Append NextLineStr
4043 replaceline LineStr''strip( NextLineStr), l
4044 deleteline l + 1
4045 endif
4046 enddo
4047 .autosave = SavedAutoSave
4048
4049 enddo
4050
4051; ---------------------------------------------------------------------------
4052defc ReflowSelectMode
4053 universal lastselectedreflowmode
4054
4055 KeyPath = '\NEPMD\User\Format\Reflow'
4056 SelectedMode = QueryConfigKey( KeyPath'\SpecialMode')
4057 Available = ReflowGetAvailableModes()
4058 Selection = wordpos( SelectedMode, Available) + 1 -- + 1 because -auto- is prepended
4059 Title = 'Select a mode for reflow'copies( ' ', 20)
4060 List = '/-auto-/'translate( Available, '/', ' ')
4061 Text = 'Available reflow modes:'
4062 ret = ListBox( Title,
4063 List,
4064 '/~Set/~Auto/'CANCEL__MSG, -- buttons
4065 0, 0, --5, 5, -- top, left,
4066 Min( words( List), 12), 40, -- height, width
4067 GethWndC( APP_HANDLE) || atoi( Selection) || atoi( 1) || atoi( 0) ||
4068 Text\0)
4069 -- Parse return string
4070 parse value ret with Button 2 Select \0
4071 Button = asc( Button)
4072 if Button = 1 then -- Set
4073 if Select = '-auto-' then
4074 Select = 0
4075 endif
4076 fSwitchSelected = 1
4077 WriteConfigKey( KeyPath'\SpecialMode', Select)
4078 elseif Button = 2 then -- Auto
4079 Select = 0
4080 WriteConfigKey( KeyPath'\SpecialMode', Select)
4081 fSwitchSelected = 1
4082 else -- Cancel
4083 rc = 31
4084 fSwitchSelected = 0
4085 endif
4086
4087 if fSwitchSelected then
4088 WriteConfigKey( KeyPath'\SpecialMode', Select)
4089 if Select = 0 then
4090 SelectedMode = GetMode()
4091 else
4092 SelectedMode = Select
4093 endif
4094 if SelectedMode <> lastselectedreflowmode then
4095 if isadefc( 'RefreshFormatMenu') then
4096 'RefreshFormatMenu'
4097 endif
4098 lastselectedreflowmode = SelectedMode
4099 endif
4100 endif
4101
4102; ---------------------------------------------------------------------------
4103defproc ReflowGetSelectedMode
4104 FallBackMode = 'TEXT'
4105 KeyPath = '\NEPMD\User\Format\Reflow'
4106 SelectedMode = QueryConfigKey( KeyPath'\SpecialMode')
4107 if not SelectedMode then
4108 SelectedMode = GetMode()
4109 endif
4110 Available = ReflowGetAvailableModes()
4111 if not wordpos( SelectedMode, Available) then
4112 SelectedMode = FallBackMode
4113 endif
4114 return SelectedMode
4115
4116; ---------------------------------------------------------------------------
4117defproc ReflowGetReflowMargins
4118 universal header_width
4119
4120 KeyPath = '\NEPMD\User\Mode\TEXT\Reflow'
4121 i = QueryConfigKey( KeyPath'\Margins\Selected')
4122 if i = 1 then
4123 ReflowMargins = '1 'header_width' 1'
4124 elseif i = 3 then
4125 ReflowMargins = .margins
4126 else
4127 new = QueryConfigKey( KeyPath'\Margins\'i)
4128 ReflowMargins = new
4129 endif
4130 return ReflowMargins
4131
4132; ---------------------------------------------------------------------------
4133defc Reflow2ReflowMargins
4134 ReflowMargins = ReflowGetReflowMargins()
4135 if FileIsMarked() then
4136 'ReflowMark' ReflowMargins
4137 else
4138 'ReflowAll' ReflowMargins
4139 endif
4140
4141; ---------------------------------------------------------------------------
4142defc ReflowAll2ReflowMargins
4143 ReflowMargins = ReflowGetReflowMargins()
4144 'ReflowAll' ReflowMargins
4145
4146; ---------------------------------------------------------------------------
4147; Syntax: reflow_all [<margins>]
4148defc Reflow_All, ReflowAll
4149 call NextCmdAltersText()
4150 Savedmargins = .margins
4151 if arg( 1) <> '' then
4152 .margins = arg( 1)
4153 endif
4154 call pSave_Mark( SavedMark)
4155 call pSave_Pos( SavedPos)
4156 n = 0
4157 display -1
4158 fstopit = 0
4159 top
4160 do forever
4161 getline line
4162 do while line = '' | -- Skip over blank lines or
4163 (lastpos( ':', line) = 1 & pos( '.', line) = length( line)) | -- lines containing only a GML tag or
4164 substr( line, 1, 1) = '.' -- SCRIPT commands
4165 if .line = .last then
4166 fstopit = 1
4167 leave
4168 endif
4169 down
4170 getline line
4171 enddo
4172 if fstopit then
4173 leave
4174 endif
4175 startline = .line
4176 unmark
4177 markline
4178 call pFind_Blank_Line()
4179 if .line <> startline then
4180 up
4181 else
4182 bottom
4183 endif
4184 markline
4185 getmark prevfirstline, prevlastline
4186 n = n + (prevlastline - prevfirstline) + 1
4187 reflow
4188 getmark firstline, lastline
4189 if lastline = .last then
4190 leave
4191 endif
4192 lastline + 1
4193 enddo
4194 display 1
4195 call pRestore_Mark( SavedMark)
4196 call pRestore_Pos( SavedPos)
4197 if arg( 1) <> '' then
4198 .margins = SavedMargins
4199 endif
4200
4201 'SayHint 'n' lines reflowed.'
4202 'HighlightCursor'
4203
4204; ---------------------------------------------------------------------------
4205defc ReflowMark2ReflowMargins
4206 ReflowMargins = ReflowGetReflowMargins()
4207 'ReflowMark' ReflowMargins
4208
4209; ---------------------------------------------------------------------------
4210; Syntax: ReflowMark [<margins>]
4211defc ReflowMark
4212 SavedMarktype = marktype()
4213 mt = strip( leftstr( SavedMarktype, 1))
4214 if mt = '' then
4215 'SayError 'NO_MARK__MSG
4216 stop
4217 endif
4218
4219 getmark firstline, lastline, firstcol, lastcol, fid
4220 getfileid curfid
4221 if curfid <> fid then
4222 unmark
4223 'SayError 'MARKED_OTHER__MSG
4224 stop
4225 endif
4226
4227 if not Check_Mark_On_Screen() then
4228 'SayError 'MARK_OFF_SCREEN__MSG
4229 stop
4230 endif
4231
4232 if mt = 'C' then
4233 -- Change to line mark
4234 if lastCol = 0 then
4235 lastLine = lastLine - 1
4236 endif
4237 firstcol = 1
4238 lastcol = MAXCOL
4239 unmark
4240 call pSet_Mark( firstline, lastline, firstcol, lastcol, 'LINE', fid)
4241 mt = 'L'
4242 endif
4243
4244 SavedMargins = .margins
4245 if arg( 1) <> '' then
4246 .margins = arg( 1)
4247 endif
4248 call NextCmdAltersText()
4249 display -1
4250 n = 0
4251
4252 n = n + (lastline - firstline) + 1
4253 if mt = 'B' then
4254 'box r'
4255 elseif mt = 'L' then
4256 reflow
4257 endif
4258
4259 display 1
4260 if arg( 1) <> '' then
4261 .margins = SavedMargins
4262 endif
4263
4264 'SayHint 'n' marked lines reflowed.'
4265 'HighlightCursor'
4266
4267; ---------------------------------------------------------------------------
4268defc ReflowPar2ReflowMargins
4269 ReflowMargins = ReflowGetReflowMargins()
4270 'ReflowPar' ReflowMargins
4271
4272; ---------------------------------------------------------------------------
4273; Syntax: ReflowPar [<margins>]
4274; Ignores mark. To reflow a marked area, use ReflowMark.
4275defc ReflowPar
4276 saved_margins = .margins
4277 if arg( 1) <> '' then
4278 .margins = arg( 1)
4279 endif
4280 call NextCmdAltersText()
4281 display -1
4282
4283 call Text_Reflow()
4284
4285 display 1
4286 if arg( 1) <> '' then
4287 .margins = saved_margins
4288 endif
4289
4290; ---------------------------------------------------------------------------
4291; Standard text reflow, moved from Alt+P definition in STDKEYS.E.
4292; Only called from Alt+P if no mark exists; users wishing to call
4293; this from their own code must save & restore the mark themselves
4294; if that's desired.
4295defproc Text_Reflow
4296 call NextCmdAltersText()
4297 KeyPath = '\NEPMD\User\Format\Reflow'
4298 ReflowNext = QueryConfigKey( KeyPath'\Par')
4299 if .line then
4300 getline line
4301 if line <> '' then -- If currently on a blank line, don't reflow.
4302 oldcursory = .cursory
4303 oldcursorx = .cursorx
4304 oldline = .line
4305 oldcol = .col
4306 unmark
4307 mark_line
4308 call pFind_Blank_Line()
4309 -- Ver 3.11: Slightly revised test works better with GML sensitivity.
4310 if .line <> oldline then
4311 up
4312 else
4313 bottom
4314 endif
4315 mark_line
4316 reflow
4317 if ReflowNext then
4318 -- Position on next paragraph (like PE)
4319 call pFind_Blank_Line()
4320 for i = .line + 1 to .last
4321 getline line, i
4322 if line <> '' then
4323 .lineg = i
4324 .col = 1
4325 .cursory = oldcursory
4326 .line = i
4327 leave
4328 endif
4329 endfor
4330 else
4331 -- or like old E
4332 getmark firstline, lastline
4333 firstline
4334 .cursory = oldcursory
4335 .cursorx = oldcursorx
4336 oldline
4337 .col = oldcol
4338 endif
4339 unmark
4340 endif
4341 'HighlightCursor'
4342 endif
4343
4344; ---------------------------------------------------------------------------
4345definit -- Variable is null if alt_R is not active.
4346 universal alt_R_active -- For E3/EOS2, it's 1 if alt_R is active.
4347 alt_R_active = '' -- For EPM, it's set to querycontrol(messageline).
4348
4349; ---------------------------------------------------------------------------
4350defc ReflowBlock
4351 universal alt_R_active,tempofid
4352 universal alt_R_space
4353
4354 call NextCmdAltersText()
4355 if alt_R_active <> '' then
4356 call pBlock_Reflow( 1, alt_R_space, tempofid) -- Complete the reflow.
4357 'SetMessageline '\0
4358 'ToggleFrame 2 'alt_R_active -- Restore status of messageline.
4359 alt_R_active = ''
4360 return
4361 endif
4362 if pBlock_Reflow( 0, alt_R_space, tempofid) then
4363 'SayError 'PBLOCK_ERROR__MSG /* HurleyJ */
4364 return
4365 endif
4366; if marktype() <> 'BLOCK' then
4367 unmark
4368; endif
4369 alt_R_active = QueryFrameControl( 2) -- Remember if messageline on or off
4370 'ToggleFrame 2 1' -- Force it on
4371 'SetMessageLine' BLOCK_REFLOW__MSG
4372
4373; ---------------------------------------------------------------------------
4374defc Split
4375 call NextCmdAltersText()
4376 split
4377
4378; ---------------------------------------------------------------------------
4379defc SplitLines
4380 call NextCmdAltersText()
4381 call SplitLines()
4382
4383; ---------------------------------------------------------------------------
4384; Removes all empty lines
4385defc RemoveAllEmptyLines
4386 if FileIsMarked() then
4387 MarkToLineMark()
4388 getmark markfirstline, marklastline, markfirstcol, marklastcol, markfid
4389 FirstLine = markfirstline
4390 LastLine = marklastline
4391 else
4392 FirstLine = 1
4393 LastLine = .last
4394 endif
4395
4396 call NextCmdAltersText()
4397 SavedModify = .modify
4398 pSave_Pos( SavedPos)
4399 n = 0
4400 Line = 1
4401 do forever
4402 if Line > LastLine then
4403 leave
4404 endif
4405 if textline( Line) = '' then
4406 .lineg = Line
4407 deleteline
4408 LastLine = LastLine - 1
4409 n = n + 1
4410 .modify = SavedModify + 1
4411 else
4412 Line = Line + 1
4413 endif
4414 enddo
4415 pRestore_Pos( SavedPos)
4416
4417 'SayHint 'n' lines removed.'
4418
4419; ---------------------------------------------------------------------------
4420; Reduces multiple empty lines to one
4421defc RemoveMultipleEmptyLines
4422 if FileIsMarked() then
4423 MarkToLineMark()
4424 getmark markfirstline, marklastline, markfirstcol, marklastcol, markfid
4425 FirstLine = markfirstline
4426 LastLine = marklastline
4427 else
4428 FirstLine = 1
4429 LastLine = .last
4430 endif
4431
4432 call NextCmdAltersText()
4433 SavedModify = .modify
4434 pSave_Pos( SavedPos)
4435 n = 0
4436 Line = FirstLine
4437 do forever
4438 if Line >= LastLine then
4439 leave
4440 endif
4441 if textline( Line) = '' & textline( Line + 1) = '' then
4442 .lineg = Line
4443 deleteline
4444 LastLine = LastLine - 1
4445 n = n + 1
4446 .modify = SavedModify + 1
4447 else
4448 Line = Line + 1
4449 endif
4450 enddo
4451 pRestore_Pos( SavedPos)
4452
4453 'SayHint 'n' lines removed.'
4454
4455; ---------------------------------------------------------------------------
4456; Ensures that empty lines follow trailing '.' or ':' chars at a line end
4457; and ensures there exist an empty line at the end.
4458defc ReAddEmptyLines
4459 if FileIsMarked() then
4460 MarkToLineMark()
4461 getmark markfirstline, marklastline, markfirstcol, marklastcol, markfid
4462 FirstLine = markfirstline
4463 LastLine = marklastline
4464 else
4465 FirstLine = 1
4466 LastLine = .last
4467 endif
4468
4469 call NextCmdAltersText()
4470 SavedModify = .modify
4471 pSave_Pos( SavedPos)
4472 n = 0
4473 Line = FirstLine
4474 do forever
4475 if Line > LastLine then
4476 leave
4477 elseif Line = LastLine then
4478 insertline '', Line + 1
4479 n = n + 1
4480 .modify = SavedModify + 1
4481 leave
4482 elseif wordpos( rightstr( strip( textline( Line)), 1), '. :') > 0 &
4483 strip( textline( Line + 1)) <> '' then
4484 insertline '', Line + 1
4485 n = n + 1
4486 Line = Line + 2
4487 .modify = SavedModify + 1
4488 else
4489 Line = Line + 1
4490 endif
4491 enddo
4492 pRestore_Pos( SavedPos)
4493
4494 'SayHint 'n' lines added.'
4495
4496; ---------------------------------------------------------------------------
4497defc RemoveDoubleLineEnds
4498 Option = upcase( strip( arg( 1)))
4499 if Option = 'EXACT' then
4500
4501 -- Exact
4502 -- This is the old "SingleSpace" macro.
4503 -- Removes every 2nd line, if it's a blank line.
4504 -- Stops if a 2nd line is not blank. Starts at the forelast line,
4505 -- which must be blank.
4506 call NextCmdAltersText()
4507 do l = .last - 1 to 1 by -2
4508 if textline( l) <> '' then
4509 'SayError Line' l 'is not blank.'
4510 leave
4511 endif
4512 deleteline l
4513 enddo
4514
4515 else
4516
4517 -- Sloppy
4518 call NextCmdAltersText()
4519 l = .last
4520 do forever
4521 if l <= 1 then
4522 leave
4523 endif
4524
4525 if textline( l) = '' then -- If line l is empty
4526 -- Backward: line l is greater than the lines above
4527 FirstEmptyLine = l
4528 LastEmptyLine = l
4529 do l2 = l - 1 to 1 by -1
4530 if textline( l2) <> '' then
4531 leave
4532 endif
4533 LastEmptyLine = l2
4534 enddo
4535
4536 -- Backward: FirstEmptyLine is greater than the lines above
4537 NumEmptyLines = FirstEmptyLine - LastEmptyLine + 1
4538 NumDelete = (NumEmptyLines + 1) % 2
4539 do n = 1 to NumDelete
4540 deleteline l
4541 l = l - 1
4542 enddo
4543 l = l - (NumDelete - 1)
4544 else
4545 l = l - 1
4546 endif
4547 enddo
4548
4549 endif
4550
4551; ---------------------------------------------------------------------------
4552; For campatibility.
4553defc SingleSpace
4554 'RemoveDoubleLineEnds exact'
4555
4556; ---------------------------------------------------------------------------
4557; Remove double lines
4558defc RemoveDoubleLines
4559 if FileIsMarked() then
4560 MarkToLineMark()
4561 getmark markfirstline, marklastline, markfirstcol, marklastcol, markfid
4562 FirstLine = markfirstline
4563 LastLine = marklastline
4564 else
4565 FirstLine = 1
4566 LastLine = .last
4567 endif
4568
4569 call NextCmdAltersText()
4570 SavedModify = .modify
4571 pSave_Pos( SavedPos)
4572 n = 0
4573 Line = FirstLine
4574 do forever
4575 if Line > .last then
4576 leave
4577 endif
4578 if Line >= LastLine then
4579 leave
4580 endif
4581 LineStr = textline( Line)
4582 if strip( translate( LineStr, ' ', \9)) = '' then
4583 Line = Line + 1
4584 iterate
4585 endif
4586
4587 j = Line + 1
4588 do forever
4589 if j > .last then
4590 leave
4591 endif
4592 if LineStr == textline( j) then
4593 .lineg = j
4594 deleteline
4595 n = n + 1
4596 .modify = SavedModify + 1
4597 else
4598 j = j + 1
4599 endif
4600 enddo
4601
4602 Line = Line + 1
4603 enddo
4604 pRestore_Pos( SavedPos)
4605
4606 'SayHint 'n' lines removed.'
4607
4608; ---------------------------------------------------------------------------
4609defc StripBlanksFromLines
4610 Option = upcase( arg( 1))
4611 fStripLeading = 0
4612 if abbrev( Option, 'L', 1) then
4613 fStripLeading = 1
4614 endif
4615
4616 if FileIsMarked() then
4617 MarkToLineMark()
4618 getmark markfirstline, marklastline, markfirstcol, marklastcol, markfid
4619 FirstLine = markfirstline
4620 LastLine = marklastline
4621 else
4622 FirstLine = 1
4623 LastLine = .last
4624 endif
4625
4626 call NextCmdAltersText()
4627 n = 0
4628 do Line = FirstLine to LastLine
4629 -- Determine LineStr before calling SearchReplaceLine
4630 getline LineStr, Line
4631 if length( LineStr) = 0 then
4632 iterate
4633 endif
4634
4635 -- Remove leading whitespace
4636 rcx1 = 1
4637 if fStripLeading then
4638 -- Running SearchReplaceLine on every line with extended grep is
4639 -- slow. Therefore avoid the call if possible.
4640 if leftstr( LineStr, 1) == ' ' | leftstr( LineStr, 1) == \9 then
4641 rcx1 = SearchReplaceLine( '^:w', '', 1, 'x', Line, 1)
4642 endif
4643 endif
4644
4645 -- Remove trailing whitespace
4646 -- Running SearchReplaceLine on every line with extended grep is
4647 -- slow. Therefore avoid the call if possible.
4648 rcx2 = 1
4649 if rightstr( LineStr, 1) == ' ' | rightstr( LineStr, 1) == \9 then
4650 rcx2 = SearchReplaceLine( ':w$', '', 1, 'x', Line, 1)
4651 endif
4652
4653 -- Count changes
4654 if rcx1 = 0 | rcx2 = 0 then
4655 n = n + 1
4656 endif
4657 enddo
4658
4659 'SayHint 'n' lines stripped.'
4660
4661; ---------------------------------------------------------------------------
4662defc CenterMark, Center
4663 call NextCmdAltersText()
4664 call pCenter_Mark()
4665
4666; ---------------------------------------------------------------------------
4667; Centers the text within the mark, linewise. Reduces 1599 as EndCol to 78
4668; to place the text at a useful place. Replaces trailing and leading
4669; whitespace with spaces. Allows for all mark types. If no mark exists, then
4670; current line is processed and then the cursor is moved to the next line.
4671defproc pcenter_mark
4672 universal header_width
4673
4674 fFileIsMarked = FileIsMarked()
4675 if not fFileIsMarked then
4676 -- Not marked: Get entire line
4677 MkFirstLine = .line
4678 MkLastLine = .line
4679 MkFirstCol = 1
4680 MkLastCol = MAXMARGIN
4681 -- Not marked: Limit to header_width
4682 TargetCol = header_width
4683 else
4684 MkType = marktype()
4685
4686 -- Convert char mark to line mark
4687 if MkType = 'CHAR' then
4688 MarkToLineMark()
4689 MkType = marktype()
4690 endif
4691
4692 getmark MkFirstLine, MkLastLine, MkFirstCol, MkLastCol, MkFid
4693
4694 if MkType = 'LINE' then
4695 -- Line mark: Get entire line(s)
4696 MkFirstCol = 1
4697 MkLastCol = MAXMARGIN
4698 -- Line mark: Limit to header_width
4699 TargetCol = header_width
4700 else
4701 -- Block mark
4702 TargetCol = MkLastCol
4703 endif
4704 endif
4705
4706 MkLineLen = MkLastCol + 1 - MkFirstCol
4707 TargetLen = TargetCol + 1 - MkFirstCol
4708
4709 do LineNum = MkFirstLine to MkLastLine
4710 -- Read line
4711 getline LineStr, LineNum
4712 TextPart = StripBlanks( substr( LineStr, MkFirstCol, MkLineLen))
4713 if TextPart = '' then
4714 iterate
4715 endif
4716
4717 -- No mark and line mark: If line is longer, don't process it
4718 if length( TextPart) > TargetLen then
4719 iterate
4720 endif
4721
4722 -- Center line
4723 NewLineStr = overlay( center( TextPart, TargetLen), LineStr, MkFirstCol)
4724 NewLineStr = StripBlanks( NewLineStr, 'T')
4725
4726 -- Replace line (pReplaceLine preserves bookmarks)
4727 pReplaceLine( NewLineStr, LineNum)
4728 enddo
4729
4730 -- Move to next line after processing if no mark exists
4731 if not fFileIsMarked then
4732 if .line < .last then
4733 down
4734 endif
4735 endif
4736
4737 return
4738
4739; ---------------------------------------------------------------------------
4740defc BackSpace
4741 universal stream_mode
4742
4743 fMarkDeleted = ReplaceMark()
4744 if fMarkDeleted then
4745 return
4746 endif
4747
4748 call NextCmdAltersText()
4749 if .col = 1 & .line > 1 & stream_mode then
4750 up
4751 l = length( textline( .line))
4752 join
4753 .col = l + 1
4754 else
4755 old_level = .levelofattributesupport
4756 if old_level & not (old_level bitand 2) then
4757 .levelofattributesupport = .levelofattributesupport + 2
4758
4759 -- If the following block is processed after rubout, but with col
4760 -- instead of col - 1, a bookmark at col is deleted, also at col after
4761 -- rubout, which was previously col + 1. Therefore:
4762 -- Delete the bookmark at .col - 1 before rubout.
4763 if .col <= 1 & stream_mode then
4764 line = .line - 1
4765 col = length( textline( line)) + 1
4766 else
4767 line = .line
4768 col = .col
4769 endif
4770 DelBookmarkAtPos( line, col - 1)
4771
4772 -- Go over all attributes at current pos.
4773 -- Required for rubout to delete the char at col - 1.
4774 -- rubout won't go over an attribute.
4775 .cursoroffset = -300
4776
4777 endif
4778
4779 -- Begin workaround for cursor just behind or at begin of a mark
4780 -- For char mark: Move mark left if cursor is on mark begin or end
4781 old_col = .col
4782 old_line = .line
4783 fCorrectMarkBegin = 0
4784 fCorrectMarkEnd = 0
4785 getfileid fid
4786 MkType = marktype()
4787 do once = 1 to 1
4788 if MkType <> 'CHAR' then
4789 leave
4790 endif
4791 getmark first_line, last_line, first_col, last_col, mkfid
4792 if fid <> mkfid then
4793 leave
4794 endif
4795 if (old_col > 1) & (first_line = old_line) & (first_line = last_line) & (first_col = old_col) then
4796 -- Cursor is on mark begin and first_line = last_line
4797 fCorrectMarkBegin = 1
4798 fCorrectMarkEnd = 1
4799 elseif (old_col > 1) & (first_line = old_line) & (first_col = old_col) then
4800 -- Cursor is on mark begin
4801 fCorrectMarkBegin = 1
4802 elseif (old_col > 0) & (last_line = old_line) & (last_col = old_col - 1) then
4803 -- Cursor is 1 col behind mark end
4804 fCorrectMarkEnd = 1
4805 endif
4806 --dprintf( first_line', 'last_line', 'first_col', 'last_col', Marktype = 'MkType ||
4807 -- ', fCorrectMarkEnd/Begin = 'fCorrectMarkEnd fCorrectMarkBegin)
4808 enddo
4809 -- End workaround for cursor just behind or at begin of a mark
4810
4811 rubout
4812
4813 -- Begin workaround for cursor just behind or at begin of a mark
4814 --MkType = wordpos( MkType, 'LINE CHAR BLOCK CHARG BLOCKG') - 1
4815 if fCorrectMarkBegin then
4816 first_col = first_col - 1 -- move first_col left
4817 endif
4818 if fCorrectMarkEnd then
4819 last_col = last_col - 1 -- move last_col left
4820 endif
4821 if fCorrectMarkBegin | fCorrectMarkEnd then
4822 pSet_Mark( first_line, last_line, first_col, last_col, MkType, fid)
4823 endif
4824 -- End workaround for cursor just behind or at begin of a mark
4825
4826 .levelofattributesupport = old_level
4827 endif
4828 'MatchFindOnMove'
4829
4830; ---------------------------------------------------------------------------
4831; Enhanced to accept a line number as arg, like the deleteline statement.
4832defc DeleteLine
4833 Line = arg( 1)
4834 pSave_Pos( SavedPos)
4835 if Line <> '' then
4836 .lineg = Line
4837 endif
4838
4839 call NextCmdAltersText()
4840 call DelAttrInLine()
4841
4842 deleteline
4843
4844 if Line <> '' then
4845 pRestore_Pos( SavedPos)
4846 endif
4847
4848; ---------------------------------------------------------------------------
4849; Delete from cursor until beginning of next word, UNDOable
4850defc DeleteUntilNextword
4851 call NextCmdAltersText()
4852 getline LineStr
4853 BegCur = .col
4854 LenLine = length( LineStr)
4855 if LenLine >= BegCur then
4856 for i = BegCur to LenLine -- delete remainder of word
4857 if substr( LineStr, i, 1) <> ' ' then
4858 DelBookmarkAtPos()
4859 -- Go over all attributes at current pos.
4860 -- Required for deletechar to delete the char at col.
4861 -- deletechar won't go over an attribute.
4862 .cursoroffset = 0
4863 deletechar
4864 else
4865 leave
4866 endif
4867 endfor
4868 for j = i to LenLine -- delete delimiters following word
4869 if substr( LineStr, j, 1) == ' ' then
4870 DelBookmarkAtPos()
4871 -- Go over all attributes at current pos.
4872 -- Required for deletechar to delete the char at col.
4873 -- deletechar won't go over an attribute.
4874 .cursoroffset = 0
4875 deletechar
4876 else
4877 leave
4878 endif
4879 endfor
4880 endif
4881
4882; ---------------------------------------------------------------------------
4883defc DeleteUntilEndLine
4884 call NextCmdAltersText()
4885 l = length( textline( .line))
4886 DelBookmarkInRegion( .line, .col, .line, l)
4887 erase_end_line -- Ctrl-Del is the PM way.
4888
4889; ---------------------------------------------------------------------------
4890defc EndFile
4891 universal stream_mode
4892 if stream_mode then
4893 bottom
4894 endline
4895 else
4896 if .line = .last and .line then
4897 endline
4898 endif
4899 bottom
4900 endif
4901 'MatchFindOnMove'
4902
4903; ---------------------------------------------------------------------------
4904; If arg( 1) specified and > 0: Set cursor to pos of pointer.
4905defc MarkWord
4906 if arg( 1) then
4907 'MH_GoToLastClick'
4908 unmark
4909 endif
4910 call pMark_Word()
4911
4912; ---------------------------------------------------------------------------
4913; If arg( 1) specified and > 0: Set cursor to pos of pointer.
4914defc MarkSentence
4915 if arg( 1) then
4916 'MH_GoToLastClick'
4917 unmark
4918 endif
4919 call mark_sentence()
4920
4921; ---------------------------------------------------------------------------
4922; If arg( 1) specified and > 0: Set cursor to pos of pointer.
4923defc MarkParagraph
4924 if arg( 1) then
4925 'MH_GoToLastClick'
4926 unmark
4927 endif
4928 call mark_paragraph()
4929
4930; ---------------------------------------------------------------------------
4931defc ExtendSentence
4932 call mark_through_next_sentence()
4933
4934; ---------------------------------------------------------------------------
4935defc ExtendParagraph
4936 call mark_through_next_paragraph()
4937
4938; ---------------------------------------------------------------------------
4939; If arg( 1) specified and > 0: Set cursor to pos of pointer.
4940defc MarkToken
4941 if arg( 1) then
4942 'MH_GoToLastClick'
4943 endif
4944
4945 if Find_Token( startcol, endcol) then
4946 KeyPath = '\NEPMD\User\Mark\WordMarkType'
4947 WordMarkType = QueryConfigKey( KeyPath)
4948 if WordMarkType = 'B' then
4949 MkType = 'BLOCK'
4950 else
4951 MkType = 'CHAR'
4952 endif
4953 getfileid fid
4954 call pSet_Mark( .line, .line, startcol, endcol, MkType, fid)
4955 -- Copy mark to shared text buffer
4956 'Copy2SharBuff'
4957 endif
4958
4959; ---------------------------------------------------------------------------
4960defc UppercaseWord
4961 call NextCmdAltersText()
4962 call pSave_Pos( savepos)
4963 call pSave_Mark( savemark)
4964 call pMark_Word()
4965 call pUpperCase()
4966 call pRestore_Mark( savemark)
4967
4968; ---------------------------------------------------------------------------
4969defc LowercaseWord
4970 call NextCmdAltersText()
4971 call pSave_Pos( savepos)
4972 call pSave_Mark( savemark)
4973 call pMark_Word()
4974 call pLowerCase()
4975 call pRestore_Mark( savemark)
4976 call pRestore_Pos( savepos)
4977
4978; ---------------------------------------------------------------------------
4979defc UppercaseMark
4980 call NextCmdAltersText()
4981 call pUpperCase()
4982
4983; ---------------------------------------------------------------------------
4984defc LowercaseMark
4985 call NextCmdAltersText()
4986 call pLowerCase()
4987
4988; ---------------------------------------------------------------------------
4989define
4990compile if not defined( UPPERCHARS)
4991 UPPERCHARS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZŽ™š'
4992compile endif
4993compile if not defined( LOWERCHARS)
4994 LOWERCHARS = 'abcdefghijklmnopqrstuvwxyz„”'
4995compile endif
4996
4997; ---------------------------------------------------------------------------
4998; Toggles case of word under cursor: lower -> Mixed -> UPPER -> lower
4999defc CaseWord
5000 call pSave_Pos( savepos)
5001
5002 -- find_token won't take '.' and '_' as word boundaries
5003 rcx = Find_Token( startcol, endcol)
5004
5005 if rcx <> 1 & .col > 1 then
5006 -- Inspect tokens left from cursor
5007 .col = .col - 1
5008 rcx = Find_Token( startcol, endcol)
5009 endif
5010 if rcx <> 1 then
5011 call pRestore_Pos( savepos)
5012 return
5013 endif
5014
5015 getline LineStr, .line
5016 LeftLineStr = substr( LineStr, 1, Max( 0, startcol - 1))
5017 Wrd = substr( LineStr, startcol, Max( 0, endcol - startcol + 1))
5018 RightLineStr = substr( LineStr, endcol + 1)
5019
5020 if verify( Wrd, LOWERCHARS, 'M') = 0 then -- no lowercase -> lowercase
5021 -- XXXX -> xxxx
5022 NewWrd = translate( Wrd, LOWERCHARS, UPPERCHARS)
5023
5024 elseif verify( Wrd, UPPERCHARS, 'M') = 0 & -- no uppercase and
5025 verify( substr( Wrd, 1, 1), LOWERCHARS, 'M') then -- first char lowercase -> Capitalize
5026 -- xxxx -> Xxxx
5027 NewWrd = translate( leftstr( Wrd, 1), UPPERCHARS, LOWERCHARS) -- first letter
5028 if length( Wrd) > 1 then
5029 NewWrd = NewWrd''translate( substr( Wrd, 2), LOWERCHARS, UPPERCHARS) -- append rest
5030 endif
5031
5032 else -- mixed case -> UPPERCASE
5033 -- xxXx -> XXXX
5034 NewWrd = translate( Wrd, UPPERCHARS, LOWERCHARS)
5035 endif
5036
5037 -- Replace line only if anything has changed to not increase .modify otherwise
5038 if NewWrd <> Wrd then
5039 call NextCmdAltersText()
5040 --replaceline LeftLineStr''NewWrd''RightLineStr
5041 .col = startcol
5042 rcx = SearchReplaceLine( Wrd, NewWrd, 1)
5043 endif
5044
5045 call pRestore_Pos( savepos)
5046
5047; ---------------------------------------------------------------------------
5048; Toggles case of char under cursor. Moves right.
5049defc CaseChar
5050 getline LineStr, .line
5051 Char = substr( LineStr, .col, 1)
5052
5053 NewChar = Char
5054 if verify( Char, LOWERCHARS, 'M') = 0 then -- no lowercase -> lowercase
5055 -- X -> x
5056 NewChar = translate( Char, LOWERCHARS, UPPERCHARS)
5057 elseif verify( Char, UPPERCHARS, 'M') = 0 then -- no uppercase -> uppercase
5058 -- x -> X
5059 NewChar = translate( Char, UPPERCHARS, LOWERCHARS)
5060 endif
5061
5062 -- Replace line only if anything has changed to not increase .modify otherwise
5063 if NewChar <> Char then
5064 call NextCmdAltersText()
5065 rcx = SearchReplaceLine( Char, NewChar, 1)
5066 endif
5067 'NextChar'
5068
5069; ---------------------------------------------------------------------------
5070defc BeginWord
5071 call pBegin_Word()
5072
5073 'MatchFindOnMove'
5074
5075; ---------------------------------------------------------------------------
5076defc EndWord
5077 call pEnd_Word()
5078
5079 'MatchFindOnMove'
5080
5081; ---------------------------------------------------------------------------
5082defc BeginFile
5083 universal stream_mode
5084
5085 if stream_mode then
5086 top
5087 beginline
5088 else
5089 if .line = 1 then
5090 beginline
5091 endif
5092 top
5093 endif
5094
5095 'MatchFindOnMove'
5096
5097; ---------------------------------------------------------------------------
5098defc DuplicateLine
5099 call NextCmdAltersText()
5100 getline line
5101 insertline line, .line + 1
5102
5103; ---------------------------------------------------------------------------
5104defc CommandDlgLine
5105 if .line then
5106 getline line
5107 'CommandLine 'line
5108 endif
5109
5110; ---------------------------------------------------------------------------
5111defc PrevWord
5112 universal stream_mode
5113
5114 if stream_mode &
5115 (.line > 1) & (.col = Max( 1, verify( textline( .line), ' '))) then
5116 up
5117 endline
5118 endif
5119 backtab_word
5120
5121 'MatchFindOnMove'
5122
5123; ---------------------------------------------------------------------------
5124defc NextWord
5125 universal stream_mode
5126
5127 if stream_mode &
5128 (((not .line) | (lastpos( ' ', textline( .line)) < .col)) & (.line < .last)) then
5129 down
5130 call pFirst_NonBlank()
5131 else
5132 tabword
5133 endif
5134
5135 'MatchFindOnMove'
5136
5137; ---------------------------------------------------------------------------
5138defc MarkPrevWord
5139 universal stream_mode
5140
5141 startline = .line
5142 startcol = .col
5143 if .line then
5144 if stream_mode &
5145 (.line > 1) & (.col = Max( 1, verify( textline( .line), ' '))) then
5146 up
5147 endline
5148 endif
5149 backtabword
5150 call Extend_Mark( startline, startcol, 0)
5151 endif
5152
5153; ---------------------------------------------------------------------------
5154defc MarkNextWord
5155 universal stream_mode
5156
5157 startline = .line
5158 startcol = .col
5159 if .line then
5160 if stream_mode &
5161 (((not .line) | (lastpos( ' ', textline( .line)) < .col)) & (.line < .last)) then
5162 down
5163 call pFirst_NonBlank()
5164 else
5165 tabword
5166 endif
5167 call Extend_Mark( startline, startcol, 1)
5168 endif
5169
5170; ---------------------------------------------------------------------------
5171defc BeginScreen
5172 if .line then
5173 .cursory = 1
5174 else
5175 .line = 1
5176 endif
5177
5178; ---------------------------------------------------------------------------
5179defc EndScreen
5180 if .line then
5181 .cursory = .windowheight
5182 else
5183 .line = 1
5184 endif
5185
5186; ---------------------------------------------------------------------------
5187defc MarkBeginScreen
5188 startline = .line
5189 startcol = .col
5190 if .line then
5191 .cursory = 1
5192 endif
5193 if .line then
5194 call Extend_Mark( startline, startcol, 0)
5195 else
5196 .line = 1
5197 endif
5198
5199defc MarkEndScreen
5200 startline = .line
5201 startcol = .col
5202 if .line then
5203 .cursory = .windowheight
5204 endif
5205 if .line then
5206 call Extend_Mark( startline, startcol, 1)
5207 else
5208 .line = 1
5209 endif
5210
5211; ---------------------------------------------------------------------------
5212; Record and playback key and menu commands
5213; The array var 'recordkeys' holds the list of \0-separated Key\1Cmd pairs.
5214; It is set by SaveKeyCmd, which is called by OtherKeys, ExecKeyCmd and
5215; ExecAccelKey. See UNDO.E:"defproc SaveKeyCmd".
5216
5217; ---------------------------------------------------------------------------
5218defproc RecKeysNew
5219 universal recfid
5220
5221 UserDir = Get_Env( 'NEPMD_USERDIR')
5222 RecFile = UserDir'\bin\last.rec'
5223 getfileid startfid
5224 getfileid recfid, RecFile
5225 if validatefileid( recfid) then
5226 call pSave_Mark( SavedMark)
5227 activatefile recfid
5228 call pSet_Mark( 1, .last, 1, length( textline( .last)), 'CHAR' , recfid)
5229 deletemark
5230 if .last > 0 then
5231 .line = .last
5232 deleteline
5233 endif
5234 --'xcom save' -- Better keep old file until recording is saved
5235 .modify = 0
5236 call pRestore_Mark( SavedMark)
5237 else
5238 'xcom E /n 'RecFile
5239 getfileid recfid
5240 .visible = 0
5241 .autosave = 0
5242 endif
5243 if .last > 0 then
5244 .line = .last
5245 deleteline
5246 endif
5247 .modify = 0
5248 activatefile startfid
5249
5250; ---------------------------------------------------------------------------
5251defproc RecKeysEnd
5252 UserDir = Get_Env( 'NEPMD_USERDIR')
5253 RecFile = UserDir'\bin\last.rec'
5254 getfileid startfid
5255 getfileid recfid, RecFile
5256 if validatefileid( recfid) then
5257 activatefile recfid
5258 'xcom Save'
5259 activatefile startfid
5260 endif
5261
5262; ---------------------------------------------------------------------------
5263defproc RecKeysCancel
5264 UserDir = Get_Env( 'NEPMD_USERDIR')
5265 RecFile = UserDir'\bin\last.rec'
5266 getfileid startfid
5267 getfileid recfid, RecFile
5268 if validatefileid( recfid) then
5269 activatefile recfid
5270 .modify = 0
5271 'xcom Quit'
5272 activatefile startfid
5273 recfid = 0
5274 endif
5275
5276; ---------------------------------------------------------------------------
5277defc RecKeysSaveAs
5278 UserDir = Get_Env( 'NEPMD_USERDIR')
5279 RecFile = UserDir'\bin\last.rec'
5280 getfileid recfid, RecFile
5281 -- Revert to make it visible and to process defload and defselect
5282 if validatefileid( recfid) then
5283 activatefile recfid
5284 'xcom Quit'
5285 endif
5286 'xcom E /d' RecFile
5287 -- Open Save-as dialog
5288 'PostMe PostMe SaveAs_Dlg' -- 2x PostMe required
5289
5290; ---------------------------------------------------------------------------
5291defproc RecKeysGetFile
5292 universal recfid
5293
5294 if validatefileid( recfid) then
5295 RecFile = recfid.filename
5296 else
5297 UserDir = Get_Env( 'NEPMD_USERDIR')
5298 RecFile = UserDir'\bin\last.rec'
5299 endif
5300 return RecFile
5301
5302; ---------------------------------------------------------------------------
5303defc RecKeysSelectFile
5304 RecFile = RecKeysGetFile()
5305 Title = 'Select a record macro file for playback'
5306 Cmd = 'RecKeysSetFile'
5307 FileMask = RecFile
5308 'FileDlg' Title','Cmd','FileMask
5309
5310; ---------------------------------------------------------------------------
5311defc RecKeysSetFile
5312 universal recfid
5313 universal recordingstate
5314
5315 RecFile = arg( 1)
5316 Text = '"'RecFile'" set as record macro file for playback.'
5317 getfileid startfid
5318 getfileid fid, RecFile
5319 if fid = '' then
5320 if Exist( RecFile) then
5321 'xcom E' RecFile
5322 .visible = 0
5323 getfileid recfid
5324 activatefile startfid
5325 'SayError 'Text
5326 recordingstate = 'P'
5327 endif
5328 else
5329 recfid = fid
5330 'SayError 'Text
5331 recordingstate = 'P'
5332 endif
5333
5334; ---------------------------------------------------------------------------
5335defc RecKeysSelectEditFile
5336 RecFile = RecKeysGetFile()
5337 Title = 'Select a record macro file to edit'
5338 Cmd = 'RecKeysEditFile'
5339 FileMask = RecFile
5340 'FileDlg' Title','Cmd','FileMask
5341
5342; ---------------------------------------------------------------------------
5343defc RecKeysEditFile
5344 RecFile = arg( 1)
5345 getfileid fid, RecFile
5346 -- Revert to make it visible and to process defload and defselect
5347 if fid then
5348 activatefile fid
5349 'xcom Quit'
5350 endif
5351 'Edit' RecFile
5352
5353; ---------------------------------------------------------------------------
5354defproc RecKeysAppendCurKey
5355 universal curkey
5356 universal recfid
5357
5358 insertline curkey, recfid.last + 1, recfid
5359 recfid.modify = 0
5360
5361; ---------------------------------------------------------------------------
5362defproc RecKeysGetNumKeys
5363 universal recfid
5364
5365 if validatefileid( recfid) then
5366 return recfid.last
5367 else
5368 return 0
5369 endif
5370
5371; ---------------------------------------------------------------------------
5372defproc RecKeysGetKey( line)
5373 universal recfid
5374
5375 getline LineStr, line, recfid
5376 return LineStr
5377
5378; ---------------------------------------------------------------------------
5379defproc AddRecordKeys
5380 universal recordingstate
5381 universal curkey
5382
5383 parse value( curkey) with KeyString \1 Cmd
5384 Cmd = strip( Cmd)
5385
5386 -- If key recording is active, add curkey to recordkeys array var
5387 if wordpos( upcase( Cmd), 'RECORDKEYS PLAYBACKKEYS') = 0 then
5388 if recordingstate = 'R' then
5389 call RecKeysAppendCurKey()
5390 endif
5391 endif
5392
5393; ---------------------------------------------------------------------------
5394defc RecordKeys
5395 universal recordingstate
5396
5397 RecordKeysKeyString = strip( MenuAccelString( 'RecordKeys'), 'L', \9)
5398 PlaybackKeysKeyString = strip( MenuAccelString( 'PlaybackKeys'), 'L', \9)
5399
5400 if recordingstate = 'R' then
5401 recordingstate = 'P'
5402 --'SayHint' REMEMBERED__MSG
5403 call RecKeysEnd()
5404 'SayHint Remembered! Press 'PlaybackKeysKeyString' to execute.'
5405 else
5406 recordingstate = 'R'
5407 call RecKeysNew()
5408 --'SayHint' CTRL_R__MSG
5409 'SayHint Remembering keys. 'RecordKeysKeyString' to finish, 'PlaybackKeysKeyString' to finish and try, Esc to cancel.'
5410 endif
5411
5412; ---------------------------------------------------------------------------
5413defc CancelRecordKeys
5414 universal recordingstate
5415
5416 recordingstate = ''
5417 call RecKeysCancel()
5418 'SayHint Key recording canceled.'
5419
5420; ---------------------------------------------------------------------------
5421defc PlaybackKeys
5422 universal recordingstate
5423 universal recfid
5424
5425 NumEntries = RecKeysGetNumKeys()
5426 PlaybackKeysKeyString = strip( MenuAccelString( 'PlaybackKeys'), 'L', \9)
5427 if recordingstate = 'R' then
5428 recordingstate = 'P'
5429 call RecKeysEnd()
5430 --'SayHint' REMEMBERED__MSG
5431 'SayHint Remembered! Press 'PlaybackKeysKeyString' to execute.'
5432 endif
5433 if recordingstate = 'P' & validatefileid( recfid) then
5434 call NextCmdAltersText()
5435 'DisableUndoRec'
5436 do line = 1 to NumEntries
5437 KeyDef = RecKeysGetKey( line)
5438 parse value( KeyDef) with Key \1 Cmd
5439 -- Execute either accel or standard (other) key
5440 if Cmd <> '' then
5441 -- Execute Cmd if defined
5442 Cmd
5443 elseif IsSingleKey( Key) then
5444 -- A standard char
5445 call Process_Key( Key)
5446 endif
5447 enddo
5448 'EnableUndoRec'
5449 else
5450 'RecKeysSelectFile'
5451 endif
5452
5453; ---------------------------------------------------------------------------
5454defc TypeTab
5455 call Process_Key( \9)
5456
5457; ---------------------------------------------------------------------------
5458defc DeleteChar
5459 universal stream_mode
5460
5461 fMarkDeleted = ReplaceMark()
5462 if fMarkDeleted then
5463 return
5464 endif
5465
5466 call NextCmdAltersText()
5467 l = 0
5468 if .line then
5469 l = length( textline( .line))
5470 endif
5471 if .line & .col > l & stream_mode then
5472 join -- Append next line to current
5473 .col = l + 1
5474 else
5475 old_level = .levelofattributesupport
5476 if old_level & not (old_level bitand 2) then
5477 .levelofattributesupport = .levelofattributesupport + 2
5478 endif
5479 DelBookmarkAtPos()
5480 -- Go over all attributes at current pos.
5481 -- Required for deletechar to delete the char at col.
5482 -- deletechar won't go over an attribute.
5483 .cursoroffset = 0
5484 -- deletechar won't go over the text end and delete the line end char.
5485 -- That is the correct behavior in line mode.
5486 deletechar
5487 .levelofattributesupport = old_level
5488 endif
5489
5490 'MatchFindOnMove'
5491
5492; ---------------------------------------------------------------------------
5493defc ScrollLockV
5494 NewValue = strip( arg( 1))
5495 if NewValue <> '' & wordpos( NewValue, '0 1') then
5496 KeyPath = '\NEPMD\User\CursorPos\ScrollLockV'
5497 fScrollLockV = QueryConfigKey( KeyPath)
5498 if NewValue <> fScrollLockV then
5499 WriteConfigKey( KeyPath, NewValue)
5500 endif
5501 endif
5502
5503; ---------------------------------------------------------------------------
5504defc ScrollLockH
5505 NewValue = strip( arg( 1))
5506 if NewValue <> '' & wordpos( NewValue, '0 1') then
5507 KeyPath = '\NEPMD\User\CursorPos\ScrollLockH'
5508 fScrollLockH = QueryConfigKey( KeyPath)
5509 if NewValue <> fScrollLockH then
5510 WriteConfigKey( KeyPath, NewValue)
5511 endif
5512 endif
5513
5514; ---------------------------------------------------------------------------
5515defc Nextline, Down
5516 NumLines = arg( 1)
5517
5518 NextCmdChangesLinePos()
5519 call UnmarkOnAnyKey()
5520 'VSyncIfKeepCursor'
5521
5522 fScrollLockV = 0
5523 if Scroll_Lock() then
5524 KeyPath = '\NEPMD\User\CursorPos\ScrollLockV'
5525 fScrollLockV = QueryConfigKey( KeyPath)
5526 endif
5527 if fScrollLockV then
5528 ScrollUpDownKey( 1, NumLines)
5529 else
5530 call UpDownKey( 1, NumLines)
5531 endif
5532
5533
5534 'MatchFindOnMove'
5535
5536; ---------------------------------------------------------------------------
5537defc PrevLine, Up
5538 NumLines = arg( 1)
5539
5540 NextCmdChangesLinePos()
5541 call UnmarkOnAnyKey()
5542 'VSyncIfKeepCursor'
5543
5544 fScrollLockV = 0
5545 if Scroll_Lock() then
5546 KeyPath = '\NEPMD\User\CursorPos\ScrollLockV'
5547 fScrollLockV = QueryConfigKey( KeyPath)
5548 endif
5549 if fScrollLockV then
5550 ScrollUpDownKey( 0, NumLines)
5551 else
5552 call UpDownKey( 0, NumLines)
5553 endif
5554
5555 if .line = 0 then
5556 -- Not for insert below
5557 KeyPath = '\NEPMD\User\Mark\LineInsert'
5558 LineInsert = QueryConfigKey( KeyPath)
5559 if LineInsert = 'A' then
5560 .lineg = 1
5561 endif
5562 endif
5563
5564 'MatchFindOnMove'
5565
5566; ---------------------------------------------------------------------------
5567defc ScrollDown
5568 NumLines = arg( 1)
5569
5570 NextCmdChangesLinePos()
5571 call UnmarkOnAnyKey()
5572 'VSyncIfKeepCursor'
5573
5574 fScrollLockV = 0
5575 if Scroll_Lock() then
5576 KeyPath = '\NEPMD\User\CursorPos\ScrollLockV'
5577 fScrollLockV = QueryConfigKey( KeyPath)
5578 endif
5579 if not fScrollLockV then
5580 ScrollUpDownKey( 1, NumLines)
5581 else
5582 call UpDownKey( 1, NumLines)
5583 endif
5584
5585 'MatchFindOnMove'
5586
5587; ---------------------------------------------------------------------------
5588defc ScrollUp
5589 NumLines = arg( 1)
5590
5591 NextCmdChangesLinePos()
5592 call UnmarkOnAnyKey()
5593 'VSyncIfKeepCursor'
5594
5595 fScrollLockV = 0
5596 if Scroll_Lock() then
5597 KeyPath = '\NEPMD\User\CursorPos\ScrollLockV'
5598 fScrollLockV = QueryConfigKey( KeyPath)
5599 endif
5600 if not fScrollLockV then
5601 ScrollUpDownKey( 0, NumLines)
5602 else
5603 call UpDownKey( 0, NumLines)
5604 endif
5605
5606 if .line = 0 then
5607 -- Not for insert below
5608 KeyPath = '\NEPMD\User\Mark\LineInsert'
5609 LineInsert = QueryConfigKey( KeyPath)
5610 if LineInsert = 'A' then
5611 .lineg = 1
5612 endif
5613 endif
5614
5615 'MatchFindOnMove'
5616
5617; ---------------------------------------------------------------------------
5618defc MarkDown
5619 NextCmdChangesLinePos()
5620 startline = .line
5621 startcol = .col
5622 call UpDownKey( 1)
5623 if startline then -- required if cursor is in line 0
5624 call Extend_Mark( startline, startcol, 1)
5625 endif
5626
5627; ---------------------------------------------------------------------------
5628defc BeginLine -- Home
5629 call UnmarkOnAnyKey()
5630 'VSyncIfKeepCursor'
5631
5632 KeyPath = '\NEPMD\User\SpecialKeys\HomeToggles'
5633 on = (QueryConfigKey( KeyPath) = 1)
5634 if on then
5635 -- Go to begin of text.
5636 -- If in area before or at begin of text, go to column 1.
5637 startline = .line
5638 startcol = .col
5639 call pFirst_NonBlank()
5640 if .line = startline and .col = startcol then
5641 beginline
5642 endif
5643 else
5644 -- standard Home
5645 beginline
5646 endif
5647
5648 'MatchFindOnMove'
5649
5650; ---------------------------------------------------------------------------
5651defc MarkBeginLine -- Sh+Home
5652 KeyPath = '\NEPMD\User\SpecialKeys\HomeToggles'
5653 on = (QueryConfigKey( KeyPath) = 1)
5654 if on then
5655 -- Go to begin of text.
5656 -- If in area before or at begin of text, go to column 1.
5657 startline = .line
5658 startcol = .col
5659 call pFirst_NonBlank()
5660 if .line = startline and .col = startcol then
5661 beginline
5662 endif
5663 if .line then
5664 call Extend_Mark( startline, startcol, 0)
5665 endif
5666 else
5667 -- standard Sh+Home
5668 startline = .line
5669 startcol = .col
5670 beginline
5671 if .line then
5672 call Extend_Mark( startline, startcol, 0)
5673 endif
5674 endif
5675
5676; ---------------------------------------------------------------------------
5677defc EndLine -- End
5678 universal endkeystartpos
5679
5680 call UnmarkOnAnyKey()
5681 'VSyncIfKeepCursor'
5682
5683 KeyPath = '\NEPMD\User\SpecialKeys\EndToggles'
5684 on = (QueryConfigKey( KeyPath) = 1)
5685 if on then
5686 -- If started from after end of text, save that as startcol.
5687 -- Go to end of text. If on end of text, go to startcol.
5688 parse value( endkeystartpos) with savedline savedcol
5689 startline = .line
5690 startcol = .col
5691 if .line then
5692 endline
5693 --call pEnd_Line() -- like endline, but ignore trailing blanks
5694 if savedline <> startline or startcol > .col then
5695 endkeystartpos = startline startcol
5696 else
5697 if startcol = .col and savedcol > .col then
5698 .col = savedcol
5699 endif
5700 endif
5701 endif
5702 else
5703 -- standard End
5704 if .line then
5705 endline
5706 endif
5707 --call pEnd_Line() -- like endline, but ignore trailing blanks
5708 endif
5709
5710 'MatchFindOnMove'
5711
5712; ---------------------------------------------------------------------------
5713defc MarkEndLine -- Sh+End
5714 universal endkeystartpos
5715
5716 KeyPath = '\NEPMD\User\SpecialKeys\EndToggles'
5717 on = (QueryConfigKey( KeyPath) = 1)
5718 if on then
5719 parse value( endkeystartpos) with savedline savedcol
5720 startline = .line
5721 startcol = .col
5722 if .line then
5723 endline
5724 --call pEnd_Line() -- like endline, but ignore trailing blanks
5725 if savedline <> startline or startcol > .col then
5726 endkeystartpos = startline startcol
5727 else
5728 if startcol = .col and savedcol > .col then
5729 .col = savedcol
5730 endif
5731 endif
5732 call Extend_Mark( startline, startcol, 1)
5733 endif
5734 else
5735 startline = .line
5736 startcol = .col
5737 --call pEnd_Line() -- like endline, but ignore trailing blanks
5738 if .line then
5739 endline
5740 call Extend_Mark( startline, startcol, 1)
5741 endif
5742 endif
5743
5744; ---------------------------------------------------------------------------
5745; Syntax: ProcessEscape [<cmd>]
5746; <cmd> is usually set to CommandLine
5747; This can be specified in STDKEYS.E.
5748defc ProcessEscape
5749 universal alt_R_active
5750 universal recordingstate
5751 universal mousemarkinginfo
5752
5753 Cmd = strip( arg( 1))
5754 parse value mousemarkinginfo with BeginDragLine BeginDragCol HighlightSwitchedOff Mt
5755
5756 sayerror 0
5757
5758 -- Set focus to client
5759 -- EPM bug:
5760 -- On dismissing a popup menu, the focus is often not set back to the edit
5761 -- window. Click into it first. Focus switching was also addded to
5762 -- ShowCursor (Ctrl+.) and ProcessEscape (Esc).
5763 'SetFocusToEditClient'
5764
5765 if recordingstate = 'R' then
5766 'CancelRecordKeys'
5767
5768 elseif alt_R_active <> '' then
5769 'SetMessageLine '\0
5770 'ToggleFrame 2 'alt_R_active -- restore status of messageline
5771 alt_R_active = ''
5772
5773 elseif mousemarkinginfo <> '' then
5774 -- Just cancel the mark action (internally defined) and don't open
5775 -- commandline. The unmarking will happen just at releasing MB 2,
5776 -- not immediately. To unmark the text immediately, another PM window
5777 -- has to be shown, like the commandline window.
5778 'MH_CancelMark'
5779
5780 -- Workaround for catching the last char of a line as last char of a mark
5781 call MouseMarkEnableHighlight()
5782
5783 else
5784 'HighlightCursor'
5785 Cmd
5786 endif
5787
5788; ---------------------------------------------------------------------------
5789defc SaveOrSaveAs
5790 fTempFile = (leftstr( .filename, 1) = '.')
5791 -- Let 'Save' open the Save-as dialog for unmodified virtual files to
5792 -- query fTempFile and PrevFilename of 'Save' correctly
5793 if .modify | fTempFile then
5794 'Save'
5795 else
5796 'SayError No changes. Press Enter to Save anyway.'
5797 'SaveAs_Dlg 0' -- better show file selector
5798 -- new optional arg, 0 => no EXIST_OVERLAY__MSG
5799 endif
5800
5801; ---------------------------------------------------------------------------
5802defc SmartSave
5803 if .modify then
5804 'Save'
5805 else
5806 'SayError No changes.'
5807 endif
5808
5809; ---------------------------------------------------------------------------
5810defc FileOrQuit
5811 if .modify then
5812 'File'
5813 else
5814 'Quit'
5815 endif
5816
5817; ---------------------------------------------------------------------------
5818defc EditFileDlg
5819 universal ring_enabled
5820 if not ring_enabled then
5821 'SayError 'NO_RING__MSG
5822 return
5823 endif
5824 'OpenDlg EDIT'
5825
5826; ---------------------------------------------------------------------------
5827defc Prevfile
5828 -- Workaround: This avoids unwanted window scrolling of the previous file.
5829 'VSyncCursor'
5830 prevfile
5831
5832; ---------------------------------------------------------------------------
5833defc NextFile
5834 -- Workaround: This avoids unwanted window scrolling of the previous file.
5835 'VSyncCursor'
5836 nextfile
5837
5838; ---------------------------------------------------------------------------
5839defc UndoLine
5840 call NextCmdAltersText()
5841 undo
5842
5843; ---------------------------------------------------------------------------
5844defc InsertToggle
5845 inserttoggle
5846 call Fixup_Cursor()
5847
5848; ---------------------------------------------------------------------------
5849defc PrevChar, Left
5850 NumCols = arg( 1)
5851
5852 call UnmarkOnAnyKey()
5853 'VSyncIfKeepCursor'
5854
5855 fScrollLockH = 0
5856 if Scroll_Lock() then
5857 KeyPath = '\NEPMD\User\CursorPos\ScrollLockH'
5858 fScrollLockH = QueryConfigKey( KeyPath)
5859 endif
5860 if fScrollLockH then
5861 'ScrollLeft' NumCols
5862 else
5863 'MoveCursorLeft' NumCols
5864 endif
5865
5866 'MatchFindOnMove'
5867
5868; ---------------------------------------------------------------------------
5869; Moves left without unmark.
5870defc MoveCursorLeft
5871 NumCols = arg( 1)
5872 if NumCols = '' then
5873 NumCols = 1
5874 elseif not IsNum( NumCols) then
5875 NumCols = 1
5876 endif
5877
5878 'VSyncIfKeepCursor'
5879
5880 do n = 1 to NumCols
5881 if .line > 1 & .col = 1 then
5882 up
5883 endline
5884 else
5885 left
5886 endif
5887 enddo
5888
5889; ---------------------------------------------------------------------------
5890defc MarkPrevChar, MarkLeft
5891 startline = .line
5892 startcol = .col
5893 if .line > 1 & .col = 1 then
5894 up
5895 endline
5896 else
5897 left
5898 endif
5899 call Extend_Mark( startline, startcol, 0)
5900
5901; ---------------------------------------------------------------------------
5902defc PrevPage, PageUp
5903 NextCmdChangesLinePos()
5904 call UnmarkOnAnyKey()
5905 'VSyncIfKeepCursor'
5906
5907 pageup
5908
5909 'MatchFindOnMove'
5910
5911; ---------------------------------------------------------------------------
5912defc NextPage, PageDown
5913 NextCmdChangesLinePos()
5914 call UnmarkOnAnyKey()
5915 'VSyncIfKeepCursor'
5916
5917 pagedown
5918
5919 'MatchFindOnMove'
5920
5921; ---------------------------------------------------------------------------
5922defc MarkPageUp
5923 NextCmdChangesLinePos()
5924 startline = .line
5925 startcol = .col
5926 pageup
5927 if .line then
5928 call Extend_Mark( startline, startcol, 0)
5929 endif
5930 if .line = 0 then
5931 -- Not for insert below
5932 KeyPath = '\NEPMD\User\Mark\LineInsert'
5933 LineInsert = QueryConfigKey( KeyPath)
5934 if LineInsert = 'A' then
5935 .line = 1
5936 endif
5937 endif
5938
5939; ---------------------------------------------------------------------------
5940defc MarkPageDown
5941 NextCmdChangesLinePos()
5942 startline = .line
5943 startcol = .col
5944 pagedown
5945 if .line then -- required if cursor is in line 0
5946 call Extend_Mark( startline, startcol, 1)
5947 endif
5948
5949; ---------------------------------------------------------------------------
5950defc NextChar, Right
5951 NumCols = arg( 1)
5952
5953 call UnmarkOnAnyKey()
5954 'VSyncIfKeepCursor'
5955
5956 fScrollLockH = 0
5957 if Scroll_Lock() then
5958 KeyPath = '\NEPMD\User\CursorPos\ScrollLockH'
5959 fScrollLockH = QueryConfigKey( KeyPath)
5960 endif
5961 if fScrollLockH then
5962 'ScrollRight' NumCols
5963 else
5964 'MoveCursorRight' NumCols
5965 endif
5966
5967 'MatchFindOnMove'
5968
5969; ---------------------------------------------------------------------------
5970; Moves right without unmark. Used for buffer.
5971defc MoveCursorRight
5972 universal cursoreverywhere
5973
5974 NumCols = arg( 1)
5975 if NumCols = '' then
5976 NumCols = 1
5977 elseif not IsNum( NumCols) then
5978 NumCols = 1
5979 endif
5980
5981 'VSyncIfKeepCursor'
5982
5983 if .line then
5984 l = length( textline( .line))
5985 else
5986 l = .col
5987 endif
5988 if (.line < .last) & (.col > l) & not cursoreverywhere then
5989 down
5990 beginline
5991 elseif (.line = .last) & (.col > l) & not cursoreverywhere then
5992 -- nop
5993 else
5994 right
5995 endif
5996
5997; ---------------------------------------------------------------------------
5998defc MarkNextChar, MarkRight
5999 startline = .line
6000 startcol = .col
6001 if .line then
6002 l = length( textline( .line))
6003 else
6004 l = .col
6005 endif
6006 if .line < .last & .col > l then
6007 down
6008 beginline
6009 elseif .line <> .last | .col <= l then
6010 right
6011 endif
6012 call Extend_Mark( startline, startcol, 1)
6013
6014/*
6015; ---------------------------------------------------------------------------
6016defc BeginFile
6017 .line = 1
6018 beginline
6019
6020; ---------------------------------------------------------------------------
6021defc EndFile
6022 .line = .last
6023 endline
6024*/
6025
6026; ---------------------------------------------------------------------------
6027defc MarkBeginFile
6028 NextCmdChangesLinePos()
6029 startline = .line
6030 startcol = .col
6031 .line = 1
6032 beginline
6033 if startline then -- required if cursor was on line 0
6034 call Extend_Mark( startline, startcol, 0)
6035 end
6036
6037; ---------------------------------------------------------------------------
6038defc MarkEndFile
6039 NextCmdChangesLinePos()
6040 startline = .line
6041 startcol = .col
6042 .line = .last
6043 if .line then -- required if cursor was on line 0
6044 endline
6045 call Extend_Mark( startline, startcol, 1)
6046 endif
6047
6048; ---------------------------------------------------------------------------
6049defc ScrollLeft
6050 NumCols = arg( 1)
6051 if NumCols = '' then
6052 NumCols = 1
6053 elseif not IsNum( NumCols) then
6054 NumCols = 1
6055 endif
6056
6057 call UnmarkOnAnyKey()
6058 'VSyncIfKeepCursor'
6059
6060 do n = 1 to NumCols
6061 oldcursorx = .cursorx
6062 if .col - .cursorx then
6063 .col = .col - .cursorx
6064 .cursorx = oldcursorx
6065 elseif .cursorx > 1 then
6066 left
6067 endif
6068 enddo
6069
6070 'MatchFindOnMove'
6071
6072; ---------------------------------------------------------------------------
6073defc ScrollRight
6074 NumCols = arg( 1)
6075 if NumCols = '' then
6076 NumCols = 1
6077 elseif not IsNum( NumCols) then
6078 NumCols = 1
6079 endif
6080
6081 call UnmarkOnAnyKey()
6082 'VSyncIfKeepCursor'
6083
6084 do n = 1 to NumCols
6085 oldcursorx = .cursorx
6086 a = .col + .windowwidth - .cursorx + 1
6087 if a <= MAXCOL then
6088 .col = a
6089 .cursorx = oldcursorx
6090 elseif .col < MAXCOL then
6091 right
6092 endif
6093 enddo
6094
6095 'MatchFindOnMove'
6096
6097; ---------------------------------------------------------------------------
6098defc CenterLine
6099 call UnmarkOnAnyKey()
6100 oldline = .line
6101 .cursory = .windowheight % 2
6102 -- .cursory makes the cursor unvisible after scrolling
6103 -- and if cursor wasn't on screen before.
6104 oldline
6105
6106; ---------------------------------------------------------------------------
6107; Todo: Move marked lines
6108; Menu item: Flags:
6109; Backtab [moves text] Text
6110; [moves text over whitespace] Text Whitespace
6111; [moves text in insert mode] TextIns
6112; [moves text in insert mode over whitespace] TextIns Whitespace
6113; [moves cursor] Cursor
6114defc BackTab
6115 universal matchtab_on
6116 universal curkey
6117
6118 Options = arg( 1)
6119 if Options = '' then
6120 parse value curkey with KeyString \1 .
6121 KeyPath = '\NEPMD\User\SpecialKeys\'KeyString
6122 Options = QueryConfigKey( KeyPath)
6123 endif
6124 Options = translate( upcase( Options), ' ', ',') -- uppercase, commas to spaces
6125 fText = (wordpos( 'TEXT', Options) > 0)
6126 fTextIns = (wordpos( 'TEXTINS', Options) > 0)
6127 fCursor = (wordpos( 'CURSOR', Options) > 0)
6128 fWhitespace = (wordpos( 'WHITESPACE', Options) > 0)
6129 -- Default values
6130 if not fText & not fTextIns & not fCursor then
6131 fCursor = 1
6132 endif
6133
6134 TabWidth = word( .tabs, 1)
6135
6136 call UnmarkOnAnyKey()
6137 do once = 1 to 1
6138
6139 LineStr = textline( .line)
6140 OldLineStr = LineStr
6141 -- Handle tabs: expand them to spaces before.
6142 TabWidth = word( .tabs, 1)
6143 if pos( \9, LineStr) then
6144 rcx = TabExpandLine( .line, TabWidth)
6145 endif
6146
6147 oldcol = .col -- Store .col after tab expansion
6148 oldline = .line
6149 oldcursory = .cursory
6150
6151 -- Handle MatchTab: go to word boundaries of lines above
6152 Line = .line
6153 do i = 1 to 100
6154 if not matchtab_on then
6155 leave
6156 endif
6157 if .line < 2 then
6158 leave
6159 endif
6160
6161 -- Go one line up
6162 Line = Line - 1
6163 LineStr = textline( Line)
6164
6165 -- Ignore empty lines
6166 if StripBlanks( LineStr) = '' then
6167 iterate
6168 endif
6169
6170 -- Handle tabs: expand them to spaces before
6171 fTabExpanded = 0
6172 if pos( \9, LineStr) then
6173 rcx = TabExpandLine( Line, TabWidth)
6174 fTabExpanded = 1
6175 endif
6176
6177 .lineg = Line
6178
6179 -- Go to previous word boundary
6180 backtabword
6181
6182 -- Restore line with tabs
6183 if fTabExpanded then
6184 call pReplaceLine( LineStr, Line)
6185 endif
6186
6187 -- Check more lines if col is not < oldcol
6188 if .col >= oldcol then
6189 .col = oldcol
6190 iterate
6191 -- Check more lines if col 1 is reached
6192 elseif .col = 1 then
6193 .col = oldcol
6194 iterate
6195 else
6196 leave
6197 endif
6198 enddo
6199
6200 -- Restore scroll line and cursor line
6201 .cursory = oldcursory
6202 .line = oldline
6203
6204 if .col = oldcol then
6205 backtab
6206 endif
6207 numspc = oldcol - .col
6208
6209 if fWhitespace then
6210 -- Delete only chars in whitespace area
6211 SubText = substr( OldLineStr, .col, numspc)
6212 if strip( SubText) = '' then
6213 fDelete = 1
6214 else
6215 fDelete = 0
6216 endif
6217 else
6218 -- Delete every char
6219 fDelete = 1
6220 endif
6221
6222 if fDelete & (fText | (fTextIns & insertstate())) then
6223 -- Remove spaces instead of just moving the cursor
6224 if numspc > 0 then
6225 .col = oldcol
6226 do n = 1 to numspc
6227 'BackSpace'
6228 enddo
6229 endif
6230 endif
6231
6232 enddo
6233
6234; ---------------------------------------------------------------------------
6235; Todo: Move marked lines
6236; Menu item: Flags:
6237; Tab [moves text with spaces] Text Sapces
6238; [moves text with tab] Text Tab
6239; [moves text in insert mode with spaces] TextIns Spaces
6240; [moves text in insert mode with tab] TextIns Tab
6241; [moves cursor] Cursor
6242defc Tab
6243 universal stream_mode
6244 universal matchtab_on
6245 universal ondbcs
6246 universal curkey
6247
6248 Options = arg( 1)
6249 if Options = '' then
6250 parse value curkey with KeyString \1 .
6251 KeyPath = '\NEPMD\User\SpecialKeys\'KeyString
6252 Options = QueryConfigKey( KeyPath)
6253 endif
6254 Options = translate( upcase( Options), ' ', ',') -- uppercase, commas to spaces
6255 Options = ChangeStr( 'TABS', Options, 'TAB') -- eventually correct typo
6256 fText = (wordpos( 'TEXT', Options) > 0)
6257 fTextIns = (wordpos( 'TEXTINS', Options) > 0)
6258 fCursor = (wordpos( 'CURSOR', Options) > 0)
6259 fSpaces = (wordpos( 'SPACES', Options) > 0)
6260 fTab = (wordpos( 'TAB', Options) > 0)
6261 -- Default values
6262 if not fText & not fTextIns & not fCursor then
6263 fText = 1
6264 endif
6265 if not fCursor & not fSpaces & not fTab then
6266 fSpaces = 1
6267 endif
6268 if fCursor then
6269 fSpaces = 0
6270 fTab = 0
6271 endif
6272
6273 TabWidth = word( .tabs, 1)
6274
6275 do once = 1 to 1
6276 if fTab & (fText | (fTextIns & insertstate())) then
6277 call Process_Key( \9)
6278 leave
6279 endif
6280
6281 call UnmarkOnAnyKey()
6282
6283 oldcol = .col
6284 oldline = .line
6285 oldcursory = .cursory
6286 expandedcol = .col
6287
6288 do i = 1 to 100
6289 if not matchtab_on then
6290 leave
6291 endif
6292 if .line < 2 then
6293 leave
6294 endif
6295
6296 -- Go one line up
6297 .lineg = .line - 1
6298 LineStr = textline( .line)
6299
6300 -- Ignore empty lines
6301 if StripBlanks( LineStr) = '' then
6302 iterate
6303 endif
6304
6305 -- Handle tabs: expand them to spaces before
6306 fTabExpanded = 0
6307 if pos( \9, LineStr) then
6308 rcx = TabExpandLine( .line, TabWidth)
6309 fTabExpanded = 1
6310 endif
6311
6312 -- Go to next word boundary or to line end
6313 .col = oldcol
6314 tabword
6315 expandedcol = .col
6316
6317 -- Restore line with tabs
6318 if fTabExpanded then
6319 call pReplaceLine( LineStr, .line)
6320 endif
6321
6322 -- Check more lines if col is not > oldcol
6323 if expandedcol <= oldcol then
6324 expandedcol = oldcol
6325 iterate
6326 else
6327 leave
6328 endif
6329 enddo
6330
6331 -- Restore scroll line and cursor line
6332 .cursory = oldcursory
6333 .line = oldline
6334
6335 -- Go to tabstop col after expansion
6336 .col = expandedcol
6337
6338 if .col = oldcol then
6339 tab
6340 endif
6341
6342 if fText | (fTextIns & insertstate()) then
6343 -- Insert spaces instead of just moving the cursor
6344 numspc = .col - oldcol
6345 -- Handle DBCS
6346 do once2 = 1 to 1
6347 if not ondbcs then -- If we're on DBCS,
6348 leave
6349 endif
6350 if matchtab_on and .line > 1 then -- and didn't do a matchtab,
6351 leave
6352 endif
6353 if words( .tabs) > 1 then
6354 if not wordpos( .col, .tabs) then -- check if on a tab col.
6355 do i = 1 to words( .tabs) -- If we got shifted due to being inside a DBC,
6356 if word( .tabs, i) > oldcol then -- find the col we *should* be in, and
6357 numspc = word( .tabs, i) - oldcol -- set numspc according to that.
6358 leave
6359 endif
6360 enddo
6361 endif
6362 elseif (.col // .tabs) <> 1 then
6363 numspc = .tabs - (oldcol + .tabs - 1) // .tabs
6364 endif
6365 enddo -- once2
6366 -- Insert spaces
6367 if numspc > 0 then
6368 .col = oldcol
6369 call Process_Keys( copies( ' ', numspc))
6370 endif
6371 endif
6372
6373 enddo -- once
6374
6375; ---------------------------------------------------------------------------
6376defc BackTabWord
6377 backtabword
6378
6379; ---------------------------------------------------------------------------
6380defc TabWord
6381 tabword
6382
6383; ---------------------------------------------------------------------------
6384defc MarkUp
6385 NextCmdChangesLinePos()
6386 startline = .line
6387 startcol = .col
6388 call UpDownKey( 0)
6389 if .line then
6390 call Extend_Mark( startline, startcol, 0)
6391 endif
6392 if .line = 0 then
6393 -- Not for insert below
6394 KeyPath = '\NEPMD\User\Mark\LineInsert'
6395 LineInsert = QueryConfigKey( KeyPath)
6396 if LineInsert = 'A' then
6397 .lineg = 1
6398 endif
6399 endif
6400
6401; ---------------------------------------------------------------------------
6402defc DefaultPaste
6403 call NextCmdAltersText()
6404 KeyPath = '\NEPMD\User\Mark\DefaultPaste'
6405 next = substr( upcase( QueryConfigKey( KeyPath)), 1, 1)
6406 if next = 'L' then
6407 style = 'L'
6408 elseif next = 'B' then
6409 style = 'B'
6410 else
6411 style = 'C'
6412 endif
6413 call ReplaceMark()
6414 'Paste' style
6415
6416; ---------------------------------------------------------------------------
6417defc AlternatePaste
6418 call NextCmdAltersText()
6419 KeyPath = '\NEPMD\User\Mark\DefaultPaste'
6420 next = substr( upcase( QueryConfigKey( KeyPath)), 1, 1)
6421 if next = 'L' then
6422 altstyle = 'C'
6423 elseif next = 'B' then
6424 altstyle = 'C'
6425 else
6426 altstyle = 'L'
6427 endif
6428 call ReplaceMark()
6429 'Paste' altstyle
6430
6431; ---------------------------------------------------------------------------
6432; Insert the char from the line above at cursor position.
6433; May get executed repeatedly to copy an entire expression without
6434; cluttering the undo list at every single execution.
6435; From Luc van Bogaert.
6436defc InsertCharAbove
6437 if .line > 1 then
6438 -- suppress autosave and undo (for during repeated use)
6439 saved_autosave = .autosave
6440 .autosave = 0
6441 call NextCmdAltersText()
6442
6443 -- force overwrite mode
6444 i_s = insertstate()
6445 if i_s then
6446 inserttoggle -- Turn off insert mode
6447 endif
6448
6449 line = textline( .line - 1) -- line above
6450 char = substr( line, .col, 1)
6451 keyin char
6452
6453 if i_s then
6454 inserttoggle
6455 endif
6456
6457 .autosave = saved_autosave
6458 endif
6459
6460; ---------------------------------------------------------------------------
6461; Insert the char from the line below at cursor position.
6462; May get executed repeatedly to copy an entire expression without
6463; cluttering the undo list at every single execution.
6464; From Luc van Bogaert.
6465defc InsertCharBelow
6466 if .line < .last then
6467 -- suppress autosave and undo (for during repeated use)
6468 saved_autosave = .autosave
6469 .autosave = 0
6470 call NextCmdAltersText()
6471
6472 -- force overwrite mode
6473 i_s = insertstate()
6474 if i_s then
6475 inserttoggle -- Turn off insert mode
6476 endif
6477
6478 line = textline( .line + 1) -- line below
6479 char = substr( line, .col, 1)
6480 keyin char
6481
6482 if i_s then
6483 inserttoggle
6484 endif
6485
6486 .autosave = saved_autosave
6487 endif
6488
6489; ---------------------------------------------------------------------------
6490; Add a new line before the current, move to it, keep col.
6491defc NewLineBefore
6492 call NextCmdAltersText()
6493 insertline ''
6494 up
6495
6496; ---------------------------------------------------------------------------
6497; Add a new line after the current, move to it, keep col.
6498defc NewLineAfter
6499 call NextCmdAltersText()
6500 insertline '', .line + 1
6501 down
6502
6503; ---------------------------------------------------------------------------
6504; Define a_1, because alt_1 is only defined since ALT_1.E is redefined.
6505defc A_1
6506 'Alt_1'
6507
Note: See TracBrowser for help on using the repository browser.