Advertisement
oxyd76

Untitled

Feb 6th, 2016
1,193
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /*
  2.  *
  3.  *  Gets setup strings from .rc files and
  4.  *  creates or destroys WPS objects by them.
  5.  *  Registers and replaces classes,
  6.  *  creates keys in selected .ini files.
  7.  *  .rc file (like ini.rc in \os2)
  8.  *  is the template in text format
  9.  *  for creating .ini binary files.
  10.  *  Syntax: crobj [global opts] [[local opts1] <file1.rc>] ... [[local optsN] <fileN.rc>]
  11.  *  or: cat <file.rc> | crobj [global opts]
  12.  *  where [global opts] can be:
  13.  *  '-h' -- Give Help
  14.  *  '-I' -- One global ini file for all selected .rc's
  15.  *  '-U' -- Global undo: undo all the following .rc's
  16.  *
  17.  *  [local opts] can be:
  18.  *  '-i' -- local .ini file for one selected .rc
  19.  *  '-u' -- local undo: undo one the following .rc
  20.  *
  21.  *  (c) valerius, 2006 Jun 2,
  22.  *  _valerius (at-sign) mail (dot) ru
  23.  *  licensed under BSD license.
  24.  *
  25.  */
  26.  
  27. /*
  28.  *  ToDo: undo .rc files
  29.  *  instead of applying them;
  30.  */
  31.  
  32.  
  33. parse arg args
  34.  
  35. call ParseCmdLine args
  36.  
  37. call InitRxDlls
  38. call GetObjIds
  39.  
  40.  
  41. /* defaults: */
  42. InComment = 0
  43. countCommented = 0;
  44.  
  45. /* commentary symbols */
  46. BeginComment = '/*'
  47. EndComment   = '*/'
  48.  
  49. CommentVars = 'InComment countCommented',
  50.               'BeginComment EndComment'
  51.  
  52. if opt.Help = 1 then do
  53.   call GiveHelp
  54.   exit 0
  55. end
  56.  
  57. BackupFolder = 'Preserved'
  58. BackupID = '<PRG_BACKUPFLD>'
  59.  
  60. /* Apply several .rc files in the order */
  61. do num = 1 to infile.0
  62.  
  63.   infile = infile.num
  64.  
  65.   /* Reading all lines in order: */
  66.   if infile \= '' then
  67.     rc = stream(infile, 'c', 'open read')
  68.  
  69.   /* Process each .rc file */
  70.   lines = 0
  71.   do while lines(infile) > 0
  72.     line = linein(infile)
  73.     lines = lines + 1
  74.     line = strip(line)
  75.     call processLine line
  76.   end
  77.  
  78.   if infile \= '' then
  79.     rc = stream(infile, 'c', 'close')
  80.  
  81. end
  82.  
  83.  
  84. exit 0
  85. /* ------==========------- */
  86. ParseCmdLine: procedure expose infile. opt.
  87. args = arg(1)
  88.  
  89.  
  90. drop opt.
  91.  
  92. /*
  93.  *  opt.  -- options stem
  94.  *  opt.i -- options subtree for i'th .rc file,
  95.  *  where 'i' is .rc file number
  96.  */
  97.  
  98. opts = args
  99. count = 0
  100. inis = 0
  101. opt.ini = ''
  102.  
  103. do while opts \= ''
  104.  
  105.   count = count + 1
  106.   opt = getarg()
  107.  
  108.   if pos('-', opt) == 1 then
  109.     select
  110.       when opt = '-U'
  111.         /* Global Undo option: undo all
  112.            the following .rc files     */
  113.         then opt.Undo = 1
  114.  
  115.       when opt = '-u'
  116.         /* Local Undo: undo one
  117.            following .rc file          */
  118.         then do
  119.           count = count + 1
  120.           opt = getarg()
  121.           infile.count = opt
  122.           opt.count.Undo = 1
  123.           opt.count.Ini = opt.ini
  124.         end
  125.  
  126.       when opt = '-i'
  127.         /* Apply the following .rc files to
  128.                   this .ini file            */
  129.         then do
  130.           inis = inis + 1
  131.           count = count + 1
  132.           opt = getarg()
  133.           opt.ini = opt
  134.         end
  135.  
  136.       when opt = '-h'
  137.         /* Give Help */
  138.         then opt.Help = 1
  139.  
  140.       otherwise nop
  141.     end
  142.   else do
  143.     infile.count = opt
  144.     /* .ini file for count'th .rc file to apply */
  145.     opt.count.Ini = opt.ini
  146.   end
  147. end
  148. infile.0 = count
  149.  
  150. if count = 0 then do
  151.   infile.0 = 1
  152.   infile.1 = ''
  153. end
  154.  
  155. drop opt.ini
  156.  
  157.  
  158. return
  159. /* ------==========------- */
  160. getarg: procedure expose opts
  161.  
  162. /* Gets one word, or a line, enclosed
  163.    in quotes, from opts               */
  164.  
  165. opts = strip(opts)
  166.  
  167. if pos('"', opts) == 1 then
  168.   parse value opts with '"' opt '"' opts
  169. else
  170.   parse var opts opt opts
  171.  
  172.  
  173. return opt
  174. /* ------==========------- */
  175. InitRxDlls: procedure
  176.  
  177.   call RxFuncAdd 'SysLoadFuncs', 'rexxutil', 'SysLoadFuncs'
  178.   call SysLoadFuncs
  179.  
  180.   call RxFuncAdd 'WPToolsLoadFuncs', 'wptools', 'WPToolsLoadFuncs'
  181.   call WPToolsLoadFuncs
  182.  
  183.  
  184. return
  185. /* ------==========------- */
  186. processLine: procedure expose (CommentVars),
  187.                               lines infile,
  188.                               opt. opts. keys.
  189. line = arg(1)
  190.  
  191.  
  192. p1 = 1; p2 = 1;
  193.  
  194. do while p1 + p2 > 0
  195.  
  196.   /* Comment deleting */
  197.   /* Comments can't be nested */
  198.  
  199.   p1 = pos(BeginComment, line);
  200.   p2 = pos(EndComment, line);
  201.  
  202.   /* Deleting the first comment in a line */
  203.   if (0 < p1) & (p1 < p2) then do
  204.     line = delstr(line, p1, p2 - p1 + 2)
  205.   end; else if (0 < p2) & ((p2 < p1) | (p1 == 0)) then do
  206.     line = substr(line, p2 + 2);
  207.     InComment = 0;
  208.     countCommented = 0;
  209.   end; else if p1 > 0 then do
  210.  
  211.     line = delstr(line, p1);
  212.     InComment = 1
  213.   end
  214.  
  215.   line = strip(line)
  216.  
  217.   /* Skipping the lines inside the comment */
  218.   if InComment > 0 then countCommented = countCommented + 1;
  219.   if countCommented > 2  then return;
  220.  
  221.   /* Processing the line after deleting all the comments */
  222.   if p1 + p2 == 0 then do
  223.  
  224.     if line = '' then return;
  225.  
  226.     if pos('"', line) == 0 then do
  227.       /* Upper Case: */
  228.       line = translate(line)
  229.       parse var line keyword opt
  230.       select
  231.         when keyword == 'CODEPAGE'    then
  232.           opt.CodePage = opt
  233.  
  234.         when keyword == 'STRINGTABLE' then
  235.           if opt = 'REPLACEMODE' then
  236.             opt.Replace = 1
  237.           else
  238.             opt.Replace = 0
  239.  
  240.         when keyword == 'BEGIN'       then
  241.           opt.Section = prev
  242.  
  243.         when keyword == 'END'         then
  244.           opt.Section = ''
  245.  
  246.         otherwise nop
  247.  
  248.       end
  249.  
  250.       prev = keyword
  251.  
  252.       return;
  253.     end
  254.  
  255.     /*
  256.     parse var line '"' name '"' line
  257.      */
  258.  
  259.     call splitLine line
  260.     name = opts.app
  261.  
  262.     select
  263.  
  264.       when name == '' then return;
  265.  
  266.       when name == 'PM_InstallObject'
  267.         then call processInstallObj;
  268.  
  269.       when name == 'PM_InstallClass'
  270.         then call processInstallClass    line;
  271.  
  272.       when name == 'PM_InstallClassReplacement'
  273.         then call processInstallClassRep line;
  274.  
  275.       when name == 'PM_MigrateFolder'
  276.         then nop
  277.  
  278.       when name == 'PM_RunInstallProgram'
  279.         then nop
  280.  
  281.       otherwise
  282.         call processAddKey '"'name'"  'line;
  283.  
  284.     end;
  285.  
  286.     return;
  287.   end;
  288. end;
  289.  
  290.  
  291. return
  292. /* ------==========------- */
  293. processInstallObj: procedure expose lines,
  294.                                     infile keys.,
  295.                                     opts.
  296.  
  297.  
  298. /* Processing of the "PM_InstallObject" lines */
  299.  
  300. line = opts.key
  301. opts.setup = opts.val
  302.  
  303. parse var line opts.name ';' opts.class ';' opts.location ';' opts.opt
  304.  
  305. opts.opt = strip(opts.opt, 'T', ';')
  306.  
  307. /* Determining the Object Id */
  308. str = opts.setup
  309.  
  310. ObjId = ''
  311. do while str \= ''
  312.   parse var str parm '=' value ';' str
  313.   parm = translate(parm)
  314.   value = strip(value, 'T', ';')
  315.   if parm == 'OBJECTID' then do
  316.     ObjId = value
  317.     leave
  318.   end
  319. end
  320.  
  321. title = ''
  322. str = opts.setup
  323.  
  324. do while str \= ''
  325.   parse var str parm '=' value ';' str
  326.   parm = translate(parm)
  327.   value = strip(value, 'T', ';')
  328.   if parm == 'TITLE' then do
  329.     title = value
  330.     leave
  331.   end
  332. end
  333.  
  334.  
  335. if infile = '' then
  336.   file = 'stdin'
  337. else
  338.   file = infile
  339.  
  340. if ObjId = '' then do
  341.   ret = -255
  342.   call lineout 'stderr', 'Error 'ret': empty object id!'
  343.   call lineout 'stderr', 'rc file: 'file','
  344.   call lineout 'stderr', 'line: 'lines
  345.   exit ret
  346. end
  347.  
  348. if oprs.name = '' then opts.name = title
  349.  
  350. if opts.name = '' then do
  351.   ret = -254
  352.   call lineout 'stderr', 'Error 'ret': no object name and no title!'
  353.   call lineout 'stderr', 'rc file: 'file','
  354.   call lineout 'stderr', 'line: 'lines
  355.   exit ret
  356. end
  357.  
  358. if opts.class = '' then do
  359.   ret = -253
  360.   call lineout 'stderr', 'Error 'ret': no object class!'
  361.   call lineout 'stderr', 'rc file: 'file','
  362.   call lineout 'stderr', 'line: 'lines
  363.   exit ret
  364. end
  365.  
  366. if opts.location = '' then do
  367.   ret = -252
  368.   call lineout 'stderr', 'Error 'ret': no object location!'
  369.   call lineout 'stderr', 'rc file: 'file','
  370.   call lineout 'stderr', 'line: 'lines
  371.   exit ret
  372. end
  373.  
  374. /*
  375. call SysSleep 0.1
  376.  */
  377.  
  378. select
  379.  
  380.  when opts.opt == 'FAIL' then do
  381.    /* Do nothing if an object already exists or create
  382.       the new object if it didn't exist            */
  383.    opts.opt = 'F';
  384.    call lineout 'stderr', 'Failing if target object exist: 'ObjId'...'
  385.    rc = SysCreateObject(opts.class, opts.name, opts.location, opts.setup, opts.opt);
  386.  end;
  387.  
  388.  when opts.opt == 'PRESERVEOLD' then do
  389.   /* Preserve old object with renamed Object Id
  390.      and create new object with these settings with
  391.      the object id in these settings -- as the old
  392.      object had                                    */
  393.    opts.opt = 'R';
  394.    call lineout 'stderr', 'Preserving old 'ObjId'...'
  395.    p = pos('>', ObjId)
  396.    if p <= 0 then p = length(ObjId) + 1
  397.  
  398.    f = 0
  399.    cnt = 0
  400.    do until f
  401.      cnt = cnt + 1
  402.      newid = insert('_'cnt, ObjId, p - 1)
  403.      f = \ObjExists(newid)
  404.    end
  405.  
  406.    ret = WPToolsQueryObject(ObjId,,
  407.                             'class1',,
  408.                             'title1',,
  409.                             'setup1',,
  410.                             'location1')
  411.    if ret then do
  412.  
  413.      newname = insert('_'cnt, name, length(name))
  414.      newsetup = setup
  415.      parse var newsetup first 'OBJECTID=' second ';' last
  416.      newsetup = first'OBJECTID='newid';'last
  417.  
  418.      rc = SysCreateObject(class1, newname, location1, newsetup, 'U')
  419.  
  420.      if class1 = 'WPFolder'     |,
  421.         class1 = 'XWPFolder'    |,
  422.         class1 = 'MMFolder'     |,
  423.         class1 = 'WPUrlFolder'  |,
  424.         class1 = 'WPDesktop'
  425.      then do
  426.  
  427.        ret = WPToolsFolderContent(newid, 'objs.', F)
  428.  
  429.        if ret then do
  430.          do i = 1 to objs.0
  431.            obj = obj.i
  432.            ret = WPToolsQueryOnject(obj,,
  433.                                     'class2',,
  434.                                     'title2',,
  435.                                     'setup2',,
  436.                                     'location2')
  437.            if ret then do
  438.              parse var setup2 first 'OBJECTID=' second ';' last
  439.              location2 = newid
  440.              ret = SysMoveObject(second, location2)
  441.              ret = SysCreateObject(class2, title2, location2, setup2, 'U')
  442.            end
  443.            else do
  444.              call lineout 'stderr', 'Can''t query object properties: 'second'!'
  445.              exit -1
  446.            end
  447.          end
  448.        end
  449.        else do
  450.          call lineout 'stderr', 'Can''t query folder confent: 'newid'!'
  451.          exit -2
  452.        end
  453.      end
  454.    end
  455.  
  456.    rc = SysCreateObject(opts.class, opts.name, opts.location, opts.setup, opts.opt);
  457.  end;
  458.  
  459.  when opts.opt == 'REPLACE'     then do
  460.    /* Delete an old object and create new one      */
  461.    opts.opt = 'R';
  462.    call lineout 'stderr', 'Replacing 'ObjId'...'
  463.    rc = SysCreateObject(opts.class, opts.name, opts.location, opts.setup, opts.opt);
  464.  end;
  465.  
  466.  when opts.opt == 'RELOCATE'     then do
  467.    /* Find the object 'ObjId', move it to the new folder and apply setup string */
  468.    opts.opt = 'U'
  469.    call lineout 'stderr', 'Relocating 'ObjId' to folder: 'location'...'
  470.    rc = SysMoveObject(ObjId, opts.location)
  471.    rc = SysCreateObject(opts.class, opts.name, opts.location, opts.setup, opts.opt);
  472.  end;
  473.  
  474.  when opts.opt == 'UPDATE'      then do
  475.    /* Update properties, if an object already exists */
  476.   call lineout 'stderr', 'Updating 'ObjId'...'
  477.    opts.opt = 'U';
  478.    rc = SysCreateObject(opts.class, opts.name, opts.location, opts.setup, opts.opt);
  479.  end;
  480.  
  481.  when opts.opt == 'UPDATEONLY'  then do
  482.    /* What's the difference from 'UPDATE'? Please let me know (if you know) */
  483.    /* My hypotesis on this is that only SETUP string is updated, not other  */
  484.    call lineout 'stderr', 'Updating only setup string: 'ObjId'...'
  485.    opts.opt = 'U';
  486.    rc = SysSetObjectData(ObjId, opts.setup);
  487.  end;
  488.  
  489.  when opts.opt == 'DELETE'      then
  490.    /* Delete object with given settings            */
  491.    call DeleteObj;
  492.  
  493.  otherwise do
  494.    /* By default, Update the settings of the object */
  495.    opts.opt = 'U';
  496.    rc = SysCreateObject(opts.class, opts.name, opts.location, opts.setup, opts.opt);
  497.  end;
  498.  
  499. end;
  500.  
  501.  
  502. return
  503. /* ------==========------- */
  504. splitLine: procedure expose opts.
  505. line = arg(1)
  506. q = 0
  507.  
  508. drop opts.
  509. line = strip(line)
  510.  
  511. opts.app = quotedText()
  512. opts.key = quotedText()
  513. opts.val = quotedText()
  514. opts.comment = commentedText()
  515.  
  516. return
  517. /* ------==========------- */
  518. quotedText: procedure expose line q
  519.  
  520. p = pos('"', line, q + 1)
  521.  
  522. if p > 0 then do
  523.  
  524.   t = p
  525.   do forever
  526.     q = pos('"', line, p + 1)
  527.     if q > 1
  528.       then do
  529.         if substr(line, q - 1, 1) \= '^'
  530.           then
  531.             leave
  532.           else do
  533.             s1 = substr(line, 1, q - 2)
  534.             s2 = substr(line, q)
  535.             line = s1 || s2
  536.             p = q - 1
  537.           end
  538.       end
  539.   end
  540.  
  541.   s = substr(line, t + 1, q - t - 1)
  542.  
  543. end
  544. else
  545.   parse var line s line
  546.  
  547.  
  548. return s
  549. /* ------==========------- */
  550. commentedText: procedure expose line q
  551.  
  552. p = pos('/*', line, q + 1)
  553. if p > 0 then do
  554.  
  555.   q = pos('*/', line, p + 1)
  556.   s = substr(line, p + 2, q - p - 3)
  557.  
  558. end
  559. else
  560.   parse var line '/*' s '*/' line
  561.  
  562.   s = strip(s)
  563.   line = strip(line)
  564.  
  565.  
  566. return s
  567. /* ------==========------- */
  568. GetObjIds: procedure expose keys.
  569.  
  570. call SysIni 'USER', 'PM_Workplace:Location', 'ALL:', 'keys.'
  571.  
  572.  
  573. return
  574. /* ------==========------- */
  575. ObjExists: procedure expose keys.
  576. objid = arg(1)
  577.  
  578. /* Check if object with Id = objid exist */
  579.  
  580. do i = 1 to keys.0
  581.   key = keys.i
  582.   if objid = key then return 1
  583. end
  584.  
  585.  
  586. return 0
  587. /* ------==========------- */
  588. DeleteObj: procedure expose file lines,
  589.                             ObjId opts.
  590.  
  591.  
  592.    if \WPToolsQueryObject(opts.location,,
  593.                           'prop.Class1',,
  594.                           'prop.Title1',,
  595.                           'prop.Setup1',,
  596.                           'prop.Location1') then do
  597.      ret = -251
  598.      call lineout 'stderr', 'Error 'ret': location folder doesn''t exist!'
  599.      call lineout 'stderr', 'rc file: 'file','
  600.      call lineout 'stderr', 'line: 'lines
  601.      exit ret
  602.    end
  603.  
  604.  
  605.    if WPToolsFolderContent(opts.location, 'objs', 'F') then do
  606.  
  607.      ObjExists = 0
  608.      do i = 1 to objs.0
  609.        if WPToolsQueryObject(objs.i,,
  610.                              'prop.Class1',,
  611.                              'prop.Title1',,
  612.                              'prop.Setup1',,
  613.                              'prop.Location1')
  614.  
  615.        then do
  616.  
  617.          str = prop.Setup1
  618.          prop.ObjId1 = ''
  619.  
  620.          do while str \= ''
  621.            parse var str parm '=' value ';' str
  622.            parm = translate(parm)
  623.            value = strip(value, 'T', ';')
  624.            if parm == 'OBJECTID' then do
  625.              prop.ObjId1 = value
  626.              leave
  627.            end
  628.          end
  629.  
  630.          if opts.name  = prop.Title1 &,
  631.             opts.class = prop.Class1 &,
  632.             ObjId = prop.ObjId1  then do
  633.  
  634.            ObjExists = 1
  635.            leave
  636.  
  637.          end
  638.  
  639.        end
  640.        else do
  641.          call lineout 'stderr', 'Can''t query object properties: 'objs.i'!'
  642.          exit -250
  643.        end
  644.      end
  645.  
  646.    end
  647.    else
  648.      call lineout 'stderr', 'Can''t query folder content!: 'location' (WPToolsFolderContent)'
  649.  
  650.    if ObjExists then do
  651.      call lineout 'stderr', 'Destroying 'ObjId'...'
  652.      rc = SysDestroyObject(ObjId)
  653.    end
  654.    else do
  655.      call lineout 'stderr', 'No such object 'ObjId' with given properties!'
  656.      exit -250
  657.    end
  658.  
  659.  
  660. return
  661. /* ------==========------- */
  662. processInstallClass: procedure
  663. line = arg(1)
  664.  
  665. /* Processing of the "PM_InstallClass" lines */
  666.  
  667. parse var line '"' class '"' . '"' module '"' .
  668.  
  669. ret = SysRegisterObjectClass(class, module)
  670.  
  671. if ret \= 'ERROR:' then do
  672.   call lineout , 'Registering object class: 'class' in module: 'module', done...'
  673. end
  674. else do
  675.   call lineout , 'Registering object class: 'class' in module: 'module', fail...'
  676.   exit -248
  677. end
  678.  
  679.  
  680. return
  681. /* ------==========------- */
  682. processInstallClassRep: procedure
  683. line = arg(1)
  684.  
  685. /* Processing of the "PM_InstallClassReplacement" lines */
  686.  
  687. parse var line '"' class '"' . '"' rep '"' .
  688.  
  689. ret = SysIni('USER', 'PM_Workplace:ReplaceList', 'ALL:', 'list.')
  690.  
  691. if ret \= 'ERROR:' then do
  692.   found = 0
  693.   do i = 1 to list.0
  694.     oldclass = list.i
  695.     if oldclass == class then found = 1
  696.     replist = SysIni('USER', 'PM_Workplace:ReplaceList', oldclass)
  697.     leave
  698.   end
  699.   ending = '0000'x
  700.  
  701.   if found then do
  702.     p = length(replist)
  703.     if pos(ending, replist) == p - 1 then do
  704.       replist = delstr(replist, p)
  705.       replist = replist || rep || ending
  706.       ret = SysIni('USER', 'PM_Workplace:ReplaceList', oldclass, replist)
  707.       if ret \= 'ERROR:' then
  708.         call lineout , 'Replacing object class: 'class' by class: 'rep', done...'
  709.       else do
  710.         call lineout , 'Replacing object class: 'class' by class: 'rep', fail...'
  711.         exit -247
  712.       end
  713.     end
  714.   end
  715.   else do
  716.     replist = rep || ending
  717.     ret = SysIni('USER', 'PM_Workplace:ReplaceList', oldclass, replist)
  718.     if ret \= 'ERROR:' then
  719.       call lineout , 'Replacing object class: 'class' by class: 'rep', done...'
  720.     else do
  721.         call lineout , 'Replacing object class: 'class' by class: 'rep', fail...'
  722.         exit -247
  723.     end
  724.   end
  725. end
  726. else do
  727.   call lineout 'stderr', 'SysIni: can''t query keys list for ''PM_Workplace:ReplaceList''!'
  728.   exit -247
  729. end
  730.  
  731.  
  732. return
  733. /* ------==========------- */
  734. processAddKey: procedure
  735. line = arg(1)
  736.  
  737. /* Adding the arbitrary keys into the current .INI file */
  738.  
  739. /*
  740. parse var line '"' app '"' . '"' key '"' . '"' val '"' .
  741.  */
  742.  
  743. call splitLine line
  744.  
  745. ini = 'USER'
  746. ret = SysIni(ini, opts.app, opts.key, opts.val)
  747.  
  748. if ret \= 'ERROR:' then do
  749.   call lineout 'stderr', 'Setting app: '''opts.app''', key: '''opts.key''', value: '''opts.val''' in ini: '''ini''': Done...'
  750. end
  751. else do
  752.   call lineout 'stderr', 'Setting app: '''opts.app''', key: '''opts.key''', value: '''opts.val''' in ini: '''ini''': Fail...'
  753.   exit -246
  754. end
  755.  
  756.  
  757. return
  758. /* ------==========------- */
  759. GiveHelp:
  760.  
  761. call lineout 'stderr', ''
  762. call lineout 'stderr', 'Syntax: crobj [global opts] [[local opts1] <file1.rc>] ... [[local optsN] <fileN.rc>]'
  763. call lineout 'stderr', 'or: cat <file.rc> | crobj [global opts]'
  764. call lineout 'stderr', 'where [global opts] can be:'
  765. call lineout 'stderr', '''-h'' -- Give Help'
  766. call lineout 'stderr', '''-I'' -- One global ini file for all selected .rc''s'
  767. call lineout 'stderr', '''-U'' -- Global undo: undo all the following .rc''s '
  768. call lineout 'stderr', ''
  769. call lineout 'stderr', '[local opts] can be:'
  770. call lineout 'stderr', '''-i'' -- local .ini file for one selected .rc  '
  771. call lineout 'stderr', '''-u'' -- local undo: undo one the following .rc'
  772. call lineout 'stderr', ''
  773.  
  774.  
  775. return
  776. /* ------==========------- */
Advertisement
RAW Paste Data Copied
Advertisement