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