1 /****^  ***********************************************************
  2         *                                                         *
  3         * Copyright, (C) Honeywell Bull Inc., 1988                *
  4         *                                                         *
  5         * Copyright, (C) Honeywell Information Systems Inc., 1982 *
  6         *                                                         *
  7         * Copyright (c) 1972 by Massachusetts Institute of        *
  8         * Technology and Honeywell Information Systems, Inc.      *
  9         *                                                         *
 10         *********************************************************** */
 11 
 12 
 13 
 14 /* Change/return modes for the printer DIM */
 15 
 16 /* Created:  28 October 1974 by Noel I. Morris */
 17 /* Modified: 15 March 1977 by Noel I. Morris */
 18 /* Modified: September 1979 by D. Vinograd to add the remote_printer_modes_ entry */
 19 /* Modified: Februrary 1979 by J. Whitmore to fix order dependent if statement bug and check ranges of modes */
 20 /* Rewritten: 9 December 1981 by G. Palter to convert to mode_string_ and add "ctl_char" mode */
 21 /* Modified: 9 August 1982 by G. Palter to not append a newline to the returned old modes string */
 22 /* Modified: 26 August 1982 by G. Palter to make indent=N work */
 23 /* Modified: 25 June 1984 by C. Marker changed so that the left margin must be to the left of the right margin or an error code is returned. */
 24 
 25 
 26 /****^  HISTORY COMMENTS:
 27   1) change(87-05-11,Gilcrease), approve(87-07-31,MCR7686),
 28      audit(88-02-01,Farley), install(88-02-02,MR12.2-1019):
 29      Added the line numbers (line_nbrs) mode.
 30                                                    END HISTORY COMMENTS */
 31 
 32 
 33 /* format: style4,delnl,insnl,ifthenstmt,ifthen */
 34 
 35 
 36 prtdim_changemode:
 37      procedure (P_sdb_ptr, P_new_modes, P_old_modes, P_iostatus);
 38 
 39 
 40 /* Parameters */
 41 
 42 dcl  P_new_modes character (*) parameter;                   /* new modes to be set (if any) */
 43 dcl  P_old_modes character (*) parameter;                   /* set to modes in effect prior to change */
 44 
 45 dcl  P_sdb_ptr pointer parameter;                           /* prtdim_changemode: -> the stream's SDB (data block) */
 46 dcl  P_iostatus bit (72) aligned;                           /* prtdim_changemode: set to ios_ status */
 47 
 48 dcl  P_iocb_ptr pointer parameter;                          /* remote_printer_modes_: -> switch's I/O control block */
 49 dcl  P_code fixed binary (35) parameter;                    /* remote_printer_modes_: set to system status code */
 50 
 51 
 52 /* Local copies of parameters */
 53 
 54 dcl  code fixed binary (35);
 55 
 56 
 57 /* Remaining declarations */
 58 
 59 dcl  ios_interface bit (1) aligned;                         /* ON => caller used ios_; OFF => caller used iox_ */
 60 
 61 dcl  system_area area based (system_area_ptr);
 62 dcl  system_area_ptr pointer;
 63 
 64 dcl  (single_page_bit, print_bit) bit (1) aligned;          /* copies to build old modes string */
 65 dcl  stop_every_value fixed binary;
 66 dcl  old_modes_lth fixed binary (21);                       /* used to construct old modes string */
 67 dcl  i fixed binary (21);
 68 
 69 dcl  (mode_idx, array_idx, idx) fixed binary;
 70 dcl  legal_mode bit (1) aligned;
 71 
 72 /* format: off */
 73 dcl  save_rmarg fixed bin static;
 74 dcl  BOOLEAN_MODE_NAMES (-3:9) character (32) static options (constant) initial (
 75           "in",          "indent",     "stop",         "default",     /* -2,-1,0: special cased boolean modes */
 76           "noskip",      "single",      "non_edited",  "truncate",    "esc",
 77           "ctl_char",     "line_nbrs",    "1pg",  "print");
 78 
 79 dcl  NUMERIC_MODE_NAMES (1:5) character (32) static options (constant) initial (
 80           "stop",        "in",          "indent",      "ll",          "pl");
 81 
 82 dcl  NUMERIC_MODE_RANGES (1:5, 2) fixed binary static options (constant) initial (
 83           0,        9999,                                   /* stop:   0 through 9999 */
 84           0,         250,                                   /* in:     0 through  250 */
 85           0,         250,                                   /* indent: 0 through  250 */
 86           2,         250,                                   /* ll:     2 through  250 */
 87           2,         127);                                  /* pl:     2 through  127 */
 88 /* format: on */
 89 
 90 dcl  error_table_$bad_mode fixed binary (35) external;
 91 dcl  error_table_$inconsistent fixed binary (35) external;
 92 
 93 dcl  get_system_free_area_ entry () returns (pointer);
 94 dcl  ioa_$rsnnl entry () options (variable);
 95 dcl  mode_string_$parse entry (character (*), pointer, pointer, fixed binary (35));
 96 
 97 dcl  (addr, divide, hbound, index, lbound, length, min, null, reverse, rtrim, substr, unspec) builtin;
 98 
 99 dcl  cleanup condition;
100 
101 /*^L*/
102 
103 /* prtdim_changemode: entry (P_sdb_ptr, P_new_modes, P_old_modes, P_iostatus); */
104 
105           ios_interface = "1"b;                             /* ios_ calling sequence */
106 
107           P_iostatus = ""b;                                 /* clear returned status */
108           substr (P_iostatus, 41, 1) = "1"b;                /* set transaction terminated bit */
109 
110           sdb_ptr = P_sdb_ptr;
111           adp = null ();                                    /* iox_ attach description isn't used here */
112 
113           pcip = addr (sdb.conv_info);                      /* get pointer to conversion info */
114           go to COMMON;
115 
116 
117 /* Change/return modes for a remote printer/teleprinter */
118 
119 remote_printer_modes_:
120      entry (P_iocb_ptr, P_new_modes, P_old_modes, P_code);
121 
122           ios_interface = "0"b;                             /* iox_ calling sequence */
123 
124           P_code = 0;                                       /* clear return code */
125 
126           sdb_ptr = null ();                                /* no ios_ stream data block */
127           adp = P_iocb_ptr -> iocb.attach_data_ptr;
128 
129           pcip = addr (ad.remote_pci);
130 
131 
132 /* Setup */
133 
134 COMMON:
135           system_area_ptr = get_system_free_area_ ();
136           mode_string_info_ptr = null ();                   /* for cleanup handler */
137 
138           on condition (cleanup)
139                begin;
140                if mode_string_info_ptr ^= null () then free mode_string_info in (system_area);
141           end;
142 
143 
144 /* Build the current mode string and return it to the caller */
145 
146           if ios_interface then do;                         /* get modes in the attach data ... */
147                single_page_bit = sdb.single_page;
148                print_bit = ^sdb.noprint;
149                stop_every_value = sdb.stop_every;
150           end;
151           else do;                                          /* ... for either local or remote printer */
152                single_page_bit = ad.single_page;
153                print_bit = ^ad.noprint;
154                stop_every_value = ad.stop_every;
155           end;
156 
157           if length (P_old_modes) > 0 then do;              /* only return something if there's some room */
158                call ioa_$rsnnl (
159                     "^[^;^^^]noskip,^[^;^^^]single,^[^;^^^]non_edited,^[^;^^^]truncate,^[^;^^^]esc,^[^;^^^]ctl_char,^[^;^^^]line_nbrs,^[^;^^^]1pg,^[^;^^^]print,stop=^d,ll=^d,indent=^d,pl=^d."
160                     , P_old_modes, old_modes_lth, pci.overflow_off, pci.single_space, pci.non_edited, pci.truncate,
161                     pci.esc, pci.ctl_char, pci.line_nbrs, single_page_bit, print_bit, stop_every_value, pci.rmarg, pci.lmarg,
162                     pci.page_length);
163                if old_modes_lth > length (P_old_modes) then do;
164                                                             /* mode string is too long: truncate at nearest mode */
165                     i = index (reverse (P_old_modes), ","); /* look for the last comma */
166                     if (i > 0) then                         /* returning some modes: turn last "," into a "." */
167                          substr (P_old_modes, (length (P_old_modes) - i + 1)) = ".";
168                     else P_old_modes = "";                  /* nothing fits */
169                end;
170           end;
171 
172 
173 /* Process the new modes (if any) */
174 
175           if length (rtrim (P_new_modes)) ^= 0 then do;     /* there are new modes ... */
176 
177                call mode_string_$parse (P_new_modes, system_area_ptr, mode_string_info_ptr, code);
178                if code ^= 0 then go to ERROR_RETURN;
179 
180 
181 /* Validate that all modes are recognized and have valid values */
182 
183                do mode_idx = 1 to mode_string_info.number;
184                     mode_value_ptr = addr (mode_string_info.modes (mode_idx));
185                     if mode_value.char_valuep then          /* ... no mode may be a character value */
186                          go to BAD_MODE_VALUE;
187                     else if mode_value.boolean_valuep then do;
188                          legal_mode = "0"b;                 /* assume it's not valid */
189                          do idx = lbound (BOOLEAN_MODE_NAMES, 1) to hbound (BOOLEAN_MODE_NAMES, 1) while (^legal_mode);
190                               if mode_value.mode_name = BOOLEAN_MODE_NAMES (idx) then legal_mode = "1"b;
191                          end;
192                          if ^legal_mode then go to BAD_MODE_VALUE;
193                          if (mode_value.mode_name = "default") & (^mode_value.boolean_value) then go to BAD_MODE_VALUE;
194                                                             /* default mode can not be negated... */
195                          if (mode_value.mode_name = "stop") & (mode_value.boolean_value) then go to BAD_MODE_VALUE;
196                                                             /* "^stop" is accepted as a synonym of "stop=0" */
197                          if (mode_value.mode_name = "in") & (mode_value.boolean_value) then go to BAD_MODE_VALUE;
198                                                             /* "^in" is accepted as a synonym of "in=0" */
199                          if (mode_value.mode_name = "indent") & (mode_value.boolean_value) then go to BAD_MODE_VALUE;
200                                                             /* "^indent" is accepted as a synonym of "indent=0" */
201                     end;
202                     else /* if mode_value.numeric_valuep then */ do;
203                                                             /* must be a numeric mode */
204                          legal_mode = "0"b;                 /* assume it's not valid */
205                          do idx = lbound (NUMERIC_MODE_NAMES, 1) to hbound (NUMERIC_MODE_NAMES, 1) while (^legal_mode);
206                               if mode_value.mode_name = NUMERIC_MODE_NAMES (idx) then legal_mode = "1"b;
207                          end;
208                          if ^legal_mode then go to BAD_MODE_VALUE;
209                          idx = idx - 1;                     /* that's the nature of PL/I */
210                          if (mode_value.numeric_value < NUMERIC_MODE_RANGES (idx, 1))
211                               | (mode_value.numeric_value > NUMERIC_MODE_RANGES (idx, 2)) then
212                               go to BAD_MODE_VALUE;
213                     end;
214                end;
215 
216 
217 /* Modes are valid: update the I/O switch's data structures to relect the new modes */
218 
219                do mode_idx = 1 to mode_string_info.number;
220                     mode_value_ptr = addr (mode_string_info.modes (mode_idx));
221                     if mode_value.boolean_valuep then do;
222                          legal_mode = "0"b;
223                          do idx = lbound (BOOLEAN_MODE_NAMES, 1) to hbound (BOOLEAN_MODE_NAMES, 1) while (^legal_mode);
224                               if mode_value.mode_name = BOOLEAN_MODE_NAMES (idx) then do;
225                                    legal_mode = "1"b;
226                                    array_idx = idx;
227                               end;
228                          end;
229                          if legal_mode then
230                               go to SET_BOOLEAN_MODE (array_idx);
231                          else go to BAD_MODE_VALUE;         /* shouldn't happen, but... */
232                     end;
233                     else /* if mode_value.numeric_valuep then */ do;
234                          legal_mode = "0"b;
235                          do idx = lbound (NUMERIC_MODE_NAMES, 1) to hbound (NUMERIC_MODE_NAMES, 1) while (^legal_mode);
236                               if mode_value.mode_name = NUMERIC_MODE_NAMES (idx) then do;
237                                    legal_mode = "1"b;
238                                    array_idx = idx;
239                               end;
240                          end;
241                          if legal_mode then                 /* go set it */
242                               go to SET_NUMERIC_MODE (array_idx);
243                          else go to BAD_MODE_VALUE;         /* shouldn't happen, but ... */
244                     end;
245                     go to BAD_MODE_VALUE;                   /* should never get here */
246 
247 SET_BOOLEAN_MODE (0):                                       /* default */
248                     if ^mode_value.boolean_value then go to BAD_MODE_VALUE;
249                                                             /* was already tested, but ... */
250                     pci.modes = ""b;                        /* reset all modes */
251                     if ios_interface then do;
252                          sdb.mode = ""b;
253                          sdb.stop_every = 0;
254                     end;
255                     else do;
256                          ad.output_modes = ""b;
257                          ad.stop_every = 0;
258                     end;
259                     pci.top_label_length, pci.bot_label_length = 0;
260                                                             /* flush any labels */
261                     pci.rmarg = pci.phys_line_length;       /* reset line and page lengths also */
262                     pci.lmarg = 0;
263                     pci.page_length = pci.phys_page_length - pci.lpi;
264                     go to SET_NEXT_MODE;
265 
266 SET_BOOLEAN_MODE (1):                                       /* noskip */
267                     pci.overflow_off = mode_value.boolean_value;
268                     go to SET_NEXT_MODE;
269 
270 SET_BOOLEAN_MODE (2):                                       /* single */
271                     pci.single_space = mode_value.boolean_value;
272                     go to SET_NEXT_MODE;
273 
274 SET_BOOLEAN_MODE (3):                                       /* non_edited */
275                     pci.non_edited = mode_value.boolean_value;
276                     go to SET_NEXT_MODE;
277 
278 SET_BOOLEAN_MODE (4):                                       /* truncate */
279                     pci.truncate = mode_value.boolean_value;
280                     go to SET_NEXT_MODE;
281 
282 SET_BOOLEAN_MODE (5):                                       /* esc */
283                     pci.esc = mode_value.boolean_value;
284                     go to SET_NEXT_MODE;
285 
286 SET_BOOLEAN_MODE (6):                                       /* ctl_char */
287                     pci.ctl_char = mode_value.boolean_value;
288                     go to SET_NEXT_MODE;
289 
290 SET_BOOLEAN_MODE (7):                                       /* line_nbrs */
291                     pci.line_nbrs = mode_value.boolean_value;
292                     if pci.line_nbrs then do;               /* set */
293                          save_rmarg = pci.rmarg;
294                          pci.rmarg = min (pci.rmarg - 10, pci.phys_line_length -10 );
295                          pci.line_count = 1;
296                          pci.eol = "1"b;
297                          pci.eof = "0"b;
298                     end;
299                     else do;
300                          pci.rmarg = save_rmarg;
301                     end;
302                     go to SET_NEXT_MODE;
303 
304 SET_BOOLEAN_MODE (8):                                       /* 1pg */
305                     if ios_interface then
306                          sdb.single_page = mode_value.boolean_value;
307                     else ad.single_page = mode_value.boolean_value;
308                     go to SET_NEXT_MODE;
309 
310 SET_BOOLEAN_MODE (9):                                       /* print: sets the noprint switch which is the inverse */
311                     if ios_interface then
312                          sdb.noprint = ^mode_value.boolean_value;
313                     else ad.noprint = ^mode_value.boolean_value;
314                     go to SET_NEXT_MODE;
315 
316 SET_BOOLEAN_MODE (-1):                                      /* "^stop" is equivalent to "stop=0" */
317                     mode_value.numeric_value = 0;
318 SET_NUMERIC_MODE (1):                                       /* stop */
319                     if ios_interface then do;
320                          sdb.stop_every = mode_value.numeric_value;
321                          sdb.stop_counter = 0;
322                     end;
323                     else do;
324                          ad.stop_every = mode_value.numeric_value;
325                          ad.stop_counter = 0;
326                     end;
327                     go to SET_NEXT_MODE;
328 
329 SET_BOOLEAN_MODE (-3):                                      /* "^indent" is equivalent to "indent=0" */
330 SET_BOOLEAN_MODE (-2):                                      /* "^in" is equivalent to "in=0" */
331                     mode_value.numeric_value = 0;
332 SET_NUMERIC_MODE (2):                                       /* in */
333 SET_NUMERIC_MODE (3):                                       /* indent */
334                     pci.lmarg = mode_value.numeric_value;
335                     go to SET_NEXT_MODE;
336 
337 SET_NUMERIC_MODE (4):                                       /* ll */
338                     pci.rmarg = mode_value.numeric_value;
339                     go to SET_NEXT_MODE;
340 
341 SET_NUMERIC_MODE (5):                                       /* pl */
342                     pci.page_length = mode_value.numeric_value;
343                     go to SET_NEXT_MODE;
344 
345 SET_NEXT_MODE:
346                end;
347 
348                free mode_string_info in (system_area);      /* no longer need this data structure */
349                mode_string_info_ptr = null ();
350           end;
351 
352 
353 /* Insure consistency in the prt_conv_info data structure given the new mode settings */
354 
355           pci.rmarg = min (pci.rmarg, pci.phys_line_length);/* insure that line is not too long */
356           if pci.lmarg >= pci.rmarg then do;                /* left margin must be to left of right margin */
357                code = error_table_$inconsistent;
358                if length (P_old_modes) > 0 then             /* only return something if there's some room */
359                     call ioa_$rsnnl ("ll=^d,indent=^d.", P_old_modes, old_modes_lth, pci.rmarg, pci.lmarg);
360                goto ERROR_RETURN;
361           end;
362 
363           if pci.overflow_off then do;
364                pci.top_label_length,                        /* "noskip" and page labels are inconsistent */
365                     pci.bot_label_length = 0;
366                pci.sheets_per_page = 1;                     /* one sheet per page in noskip mode */
367                pci.page_length = pci.phys_page_length - pci.lpi;
368                                                             /* reset logical page length */
369           end;
370 
371           else                                              /* if "^noskip" mode ... */
372                pci.sheets_per_page =
373                     divide (pci.page_length + pci.lpi - 1 + pci.phys_page_length, pci.phys_page_length, 17, 0);
374                                                             /* compute physical sheets of paper per page */
375 
376           return;
377 
378 
379 /* Error returns */
380 
381 BAD_MODE_VALUE:
382           code = error_table_$bad_mode;
383 
384 
385 ERROR_RETURN:
386           if mode_string_info_ptr ^= null () then free mode_string_info in (system_area);
387 
388           if ios_interface then
389                substr (P_iostatus, 1, 36) = unspec (code);
390           else P_code = code;
391 
392           return;
393 
394 /*^L*/
395 
396 %include prt_sdb;
397 %page;
398 %include prt_info;
399 %page;
400 %include prt_conv_info;
401 %page;
402 %include remote_attach_data;
403 %page;
404 %include iocb;
405 %page;
406 %include mode_string_info;
407 
408      end prtdim_changemode;