/****************************************************************************/ /* Program PANTESTC Version 6.20 11.01.86 Panel System Screen Exerciser, C Version Environment 01 : Lattice (MS-) C version 1.04 under MS-DOS Environment 07 : Mark Williams C under CP/M-86 Environment 13-14 : C-Systems C (S,B) under MS-DOS Environment 17-18 : CI C86 (S,B) under MS-DOS Environment 19 : Lattice C version 1.04 under CP/M-86 Environment 20-23 : Lattice C (S,P,D,L) version 2.0 under MS-DOS Environment 24-25 : Digital Research C (S,B) under CP/M-86 Environment 26-27 : Digital Research C (S,B) under MS-DOS Environment 28 : Aztec C (now renumbered 83-86) Environment 30 : Xenix C (PDP-11) Environment 31-32 : Mark Williams (Intel) C (S,L) under iRMX86 Environment 33 : Unix C for NCR Tower (M68000) Environment 34 : Quantum C under QNX Environment 35 : De Smet C under MS-DOS Environment 36 : Unix C for Fortune 32:16 Environment 38 : De Smet C DOS link format under MS-DOS Environment 39 : De Smet C CP/M-86 Environment 40-43 : Lattice C (S,P,D,L) version 2.1 under MS-DOS Environment 44-45 : IBM PC Xenix (SCO) (S,M) Environment 48-49 : Altos 586 Xenix 3 (S,M) Environment 50 : Pixel Unix Environment 51 : Zilog Z8000 Zeus Environment 52 : Olivetti / AT&T 3B2-300 Unix System V.2 Environment 53 : Zilog Z8000 Zeus scc segmented compiler Environment 54 : PCS Cadmus MUNIX Environment 55 : Plexus P35 UNIX Environment 63 : Whitesmiths C for Co-Idris 8086 Environment 70 : Mark Williams MWC86 MS-DOS Mark Williams format Environment 71-72 : Mark Williams MWC86 MS-DOS MS format (S,L) Environment 73-77 : Wizard C 2.1 Small, Medium, Compact, Large, Huge Environment 80-82 : Microsoft C Version 3 Small, Medium, Large Environment 83-86 : Aztec C Version 3.2 S, LC, LD, L Environment 87 : Aztec C Version 3.2 CP/M-86 Environment 88 : Venix-86 C Environment A1-A3 : Xenix 286 Small, Medium, Large Environment A4-A6 : Xenix 286 Small, Medium, Large (DOS Cross-Dev) Environment C1 : Commodore Amiga Lattice C (8086 Cross, Native) This program is provided in source form as an example of the way in which access can be made to a panel description which was dynamically loaded. This program does everything on a full screen basis, but you can access individual fields through PAFPT if you know the number. This program needs to be linked with the Panel system subroutine library for the applicable environment, as well as the appropriate C library. The program loads screen layouts either from individual files or from a file containing details of several panels. This 'multiple panel' file consists of concatenated .pnl files, with an index file built by the pnlindx program. To use this mode, enter a commmand line parameter of '-m', followed by the file names of the multiple and index files. For an example of the incorporation of generated and compiled panel details in your application, see TESTC.C After displaying and entering the level 0 fields for a panel, you can enter a single number between 1 and 9 to overlay the corresponding level fields. ******************************************************************************/ /* define interface number as PNLnn */ #include /* C compiler selection */ #include /* field-level operations */ #include /* screen-level operations */ #include #ifndef WSL #ifndef AMIGA /* standard i/o header */ #include #endif #endif #ifdef AMIGA #include "lattice/stdio.h" #endif #define CRISISV "**** ERROR ON PANEL.VDU ****" #define CRISISA "**** INSUFFICIENT MEMORY FOR SCREEN SAVE ****" #define COPYRIGHT "PANTEST Version 6.20 Copyright 1982-85 Roundhill Computer Systems Limited" #define MSG01 "Standard place for .PNL files is current drive and/or directory" #define MSG02 "Standard pathname has been set for .PNL files:" #define MSG03 "Enter Panel file name: " #define MSG04 ": [Key ] " #define MSG05 "Unable to open output file" #define MSG06 "Unable to write to output file" #define MSG07 "Unable to load panel description" #define MSG08 "Enter Details" #define MSG09 "Repeat, Clear data, Print, Output, New, # (level) Quit [R/C/P/O/N/#/Q] " #define MSG10 "RCPONQ123456789" #define MSG11 "Cannot open multiple panel file / index" #define MSG12 "Usage: pantest -m multiplefile indexfile\n" #define MSG13 " pantest [panelname]\n" #define MSG14 "Using Multiple Panel File: " #define MSG15 "Displaying/reading fields for level %" /* #define HP150 1 to enable HP150 code for touch screen support */ #define PRNAME "PRN" /* MS-DOS print file name without colon */ #define OFNAME "PANTEST.TXT" /* Panel will be o/p to this file */ #ifndef LATTICE #define freopen(x,y,z) fopen(x,y) #endif #ifdef QNX #undef PRNAME #define PRNAME "$lpt" #undef OFNAME #define OFNAME "pantest.txt" #endif #ifdef DRC #undef PRNAME #define PRNAME "LST:" /* CP/M-86 print file name */ #endif #ifdef AMIGA #undef PRNAME #define PRNAME "PRT:" /* Amiga print file name */ #endif #ifdef NIX /* Any UNIX system */ #undef PRNAME /* Change next line to suit installation */ #define PRNAME "pantest.lst" /* Temp Xenix/Unix print file name */ #undef OFNAME #define OFNAME "pantest.txt" /* panel text will be o/p to this file */ #endif #ifdef MARKWILLIAMS #undef PRNAME #ifdef IRMX86 #define PRNAME ":SP:" /* use spooler */ #endif #ifdef MSDOS #define PRNAME "lpt1" /* MSDOS Mark Williams */ #endif #ifdef CPM86 #define PRNAME "lst:" /* CP/M-86 Mark Williams req l/c */ #endif #endif #define FALSE 0 #define TRUE 1 #define PFINIT 1 /* codes for PAFUNC functions */ #define PFTERM 2 #define PFCLS 3 #define PFBELL 6 #define PGESC 2 /* pagetf return codes */ #define PGQUERY 14 extern int PARDHI; /* set to highlight type for read */ #ifdef HP150 extern int PAHP150; /* set this to 1 to switch on touch option */ #endif extern char PAVAL[64]; /* PANEL validation string */ FILE *dump_file = PANULL; /* for text file output */ #ifdef WSL static uchar *filename = 0; /* for entered file name */ panpcb pantpcb = 0; /* the panel control block */ static char multfn[80] = 0; /* saved multiple file name */ #else static uchar *filename; /* for entered file name */ panpcb pantpcb; /* the panel control block */ static char multfn[80]; /* saved multiple file name */ #endif static uchar pnlpath[81] = {0}; /* path name for panel files */ static int firststart = TRUE; /* true if first time through ptstrt */ /****************************************************************************/ uchar *appends(esp,s2) /* Utility function to copy s2 onto (normally) the end of sp. On entry, esp points to the null at the end of sp, and the function returns a pointer to the final null of the appended string. The caller must ensure that there is enough room ! *****************************************************************************/ uchar *esp, *s2; { while (*esp++ = *s2++) ; return(esp-1); } #ifdef ENVIRON /****************************************************************************/ find_env() /* This function searches for a PNL= environment specifier. MS-DOS keeps environment strings in a segment specified by a segment pointer in the first page of the program, not usually accessible to C. If the compiler library has no getenv function, one is provided in the PANEL subroutine library. *****************************************************************************/ { uchar *work; EXTFUNC uchar *getenv(); work = getenv("PNL"); if (work != PANULL) strcpy(pnlpath,work); } #endif /****************************************************************************/ VOID ptinfo() /* If the user has not entered a panel name on the command line, we must ask him for one. And if applicable we should tell him the name of the default path which has been set for .PNL files, which may affect how he responds to such a request. This function displays that path information. *****************************************************************************/ { uchar *p,s[80], *appends(); PAMLN=4; /* move to line 4 */ if (PAMULT != -1) /* multiple panel file will be used */ { p = appends(s,MSG14); appends(p,multfn); /* get saved name */ PAMSGE(s); /* display it */ pnlpath[0] = '\0'; /* ignore any path */ return; } if (pnlpath[0] == '\0') /* no pathname in environment */ PAMSGE(MSG01); /* "no path set" */ else { PAMSGE(MSG02); /* "path set: " */ PAMLN=6; /* move to line 6 */ p=appends(s,"PNL="); /* initialise s */ appends(p,pnlpath); /* and append defined path */ PAMSGE(s); /* show PNL=pathname */ } } #define FL 50 /****************************************************************************/ int ptgetn() /* When no command line panel name has been entered, this function gets one from the user. This function provides an illustration of one method of using the PAMSGE and PAANSW fields in combination. If the user fails to enter a name again, the routine returns false. *****************************************************************************/ { int r,i; uchar *p,s[80],*appends(); static uchar s2[FL]; ptinfo(); /* give pathname info unless multiple */ PAMLN = 9; p=appends(s,MSG03); /* "enter panel name: " */ for (i = 0; i 0 && s2[i] == ' ') /* replace trailing blanks */ s2[i--] = '\0'; /* with nulls */ return(TRUE); } /****************************************************************************/ pthalt(sp) /* This utility function displays the passed message on the message line and then waits for the space bar to be pressed. *****************************************************************************/ char *sp; { char s[132]; strcpy(s,sp); strcat(s,MSG04); /* " Key " */ PAMSGE(s); do PAFUNC(PFBELL); while ((PAGETF() / 256) != ' '); } /****************************************************************************/ ptquit() /* Clear the screen, send VDU termination sequence and quit. Note that PAFUNC will do nothing if PAINIT has failed. *****************************************************************************/ { PAFUNC(PFCLS); /* Clear screen */ PAFUNC(PFTERM); /* Send terminal terminate sequence */ #ifdef OSTERM PAOSTERM(); /* Do OS termination tasks, if required */ #endif exit(0); /* All done */ } /****************************************************************************/ VOID ptaddpath() /* merge pnlpath[] and pantpcb.pf to produce a full name for MS-DOS 2 and UNIX tree-structured directories. (In other cases, pnlpath is empty). Rules: if pf contains ':' or '\' or '/' disregard pnlpath *****************************************************************************/ { uchar *p,*p2,*appends(); uchar fulln[80]; p = &fulln[0]; p2 = &pantpcb.pf[0]; if ( (PAIX(p2,'\\') != PANULL) || (PAIX(p2,'/') != PANULL) || (PAIX(p2,':') != PANULL) ) return; /* user overrides dft path */ p = appends(p,pnlpath); /* first move in dft */ p = appends(p,p2); /* then move in pantpcb.pf */ strcpy(pantpcb.pf,fulln); /* and move the result back */ } /****************************************************************************/ ptstrt() /* Carry out initialisation functions: get OS environment, clear the screen and display copyright information, and get the panel name to be processed if the user has not entered it on the command line. ******************************************************************************/ { #ifdef HP150 int i; static char hptest[] = "HP150"; #endif if (firststart) { firststart = 0; #ifdef OSINIT PAOSINIT(); /* Do OS initialisation tasks, if required */ #endif #ifdef ENVIRON find_env(); /* get environment strings, if applicable */ #endif if ( PAINIT("") != 0 ) /* read PANEL.VDU */ { printf("\n%s\n",CRISISV); /* not there, tell user */ ptquit(); } if (PASCSE(3) == -1) /* make areas for data + hl */ { printf("\n%s\n",CRISISA); /* not enough memory */ ptquit(); } PAOVTH = 0; /* use overlay technique for all levels > 0 */ PAPSLO = PAPSHI = 0; /* inhibit PANELS for all levels > 0 */ PARDHI = 3; /* change this value to a highlight type (1 - 15) which is to be used to highlight each field while the cursor is in it. Zero disables this feature */ #ifdef HP150 PAHP150 = 1; /* true causes all input fields to be touch-sensitive */ for (i = 0; i < 5; i++) { if (PAECB.termid[i] != hptest[i]) /* but if it's not an HP-150 */ { PAHP150 = 0; /* no touching allowed */ break; } } if (PAHP150) PARDHI = 1; /* recommended for HP touch mode */ #endif PAFUNC(PFINIT); /* send terminal init sequence */ } PAFUNC(PFCLS); /* clear the screen */ PAMLN = 0; PAMSGE(COPYRIGHT); /* display banner on line 0 */ if (pantpcb.pf[0] == '\0') /* no file name present on command line */ { if (ptgetn()) /* asked user, and got one */ { strcpy(pantpcb.pf,filename); } else /* user still did not enter one */ ptquit(); } ptaddpath(); /* add dft path name if not overridden */ } /****************************************************************************/ dump_panel(fname,ffsw) /* Dump panel to FILE dump_file with name 'fname'. This function uses the provided PASCNL subroutine to obtain formatted screen lines. The full screen dump is delimited with form feed if ffsw is true, otherwise with the line of hyphens which PASCNL provides when row > maxrow. The routine always appends to the end of the dump file. ******************************************************************************/ char *fname; int ffsw; { int row; int ret; EXTFUNC FILE *fopen(); #ifdef LATTICE EXTFUNC FILE *freopen(); #endif #ifdef IRMX86 if (ffsw) /* it is the spooler */ dump_file = fopen(fname,"w"); /* open it and write */ else dump_file = fopen(fname,"a"); /* open it and append */ #else #ifdef MSC3 #define AT "at" #else #define AT "a" #endif if (dump_file != PANULL) /* re-use file and append */ dump_file = freopen(fname,AT,dump_file); else /* first time through */ dump_file = fopen(fname,AT); /* open it and append */ #endif if (dump_file == PANULL) /* cannot open */ { pthalt(MSG05); /* "Cant open output" */ ptquit(); } for (row = 0; row <= PAECB.maxrow+(ffsw?0:1); row++) { /* do rows plus delim */ ret = fprintf(dump_file,"%s\n",PASCNL(row)); /* write them */ #ifndef WSL if (ret == -1) /* error */ { pthalt(MSG06); /* "Cant write output" */ ptquit(); } #endif } if (ffsw) fprintf(dump_file,"\f"); /* send form feed */ fclose(dump_file); /* close it */ } /***************************************************************************/ ptmcho(sp) /* Menu choice. Get character from user (no echo) until it is found in string *sp. Input is converted to upper case, and ? and esc functions mapped. The function returns the 'choice number' corresponding to the position in the string of the selected option. The function does not return until a valid input has been received. *****************************************************************************/ char *sp; /* string of choices */ { unsigned f; /* function from user */ char *p, /* pointer to move along string */ ch; /* char from user */ while (TRUE) { f = PAGETF(); /* get char or function */ ch = f / 256; /* char = high 8 bits */ f &= 255; /* function = low 8 bits */ switch (f) /* convert esc and query */ { /* to std pattern chars */ case PGESC: ch = '^'; /* escape matches ^ */ break; case PGQUERY: ch = '?'; /* and query matches ? */ break; default: ; /* leave all others */ } if (ch >= 'a' && ch <= 'z') ch += 'A'-'a'; /* convert to u/c */ p = sp; while (*p) if (*p++ == ch) /* search in passed string */ { PACOUT(ch); /* echo char */ return(p-sp); /* return offset+1 in string */ } PAFUNC(PFBELL); /* shout if invalid */ } } /****************************************************************************/ main(argc,argv) /* main function. argv[1] should point to user-supplied panel name, or to a '-m' to signify that two file names follow. ******************************************************************************/ int argc; char *argv[]; { int quitting; char *p,ch; int c; char tmp[40]; pantpcb.pf[0] = 0; /* null string for filename */ if ( (argc == 4) && (argv[1][0] == '-') && ( (argv[1][1] == 'm') || (argv[1][1] == 'M') ) ) /* test M option */ { if (PAMLOP(argv[2],argv[3])) /* open multiple panel file */ { printf(MSG11); exit(0); } strcpy(multfn,argv[2]); /* save name */ } else { if (argc > 2) /* filter any mistaken command lines */ { printf(MSG12); printf(MSG13); exit(0); } if (argc > 1) strcpy(pantpcb.pf,argv[1]); /* get panelname */ PAMULT = -1; /* turn off multiple panel mode */ } while (TRUE) { ptstrt(); /* initialisation */ dump_file = PANULL; /* ensure no dump file */ if (PALOOK(&pantpcb)) /* check multiple file index */ { pthalt(MSG07); pantpcb.pf[0] = '\0'; /* force ask for panel name */ goto newpanel; } if ((PALOAD(&pantpcb,FALSE,TRUE))) /* can't load panel file */ { pthalt(MSG07); ptquit(); } PAUSEP(&pantpcb,0); /* set up complete panel for use */ PAFUNC(PFCLS); /* clear the screen */ PANELS(pdisp); /* display output fields */ quitting = FALSE; while (! quitting) { PAMSGE(MSG08); /* "Enter details" */ PANELS(prjnf); /* set up numeric fields correctly */ #ifdef HP150 if (PAHP150) /* touch fields in use */ PAFUNC(10); /* Cancel all touch fields before reshow */ #endif PANELS(pshow); /* display all input fields */ for (p = &PAVAL[0],ch = 'A'; ch <= 'Z'; *p++ = ch++); *p=0; /* change paval for std validation (only allow U/C chars) */ PANELS(pread); /* read the input fields, ignore rtn */ PAMSGE(MSG09); /* R/C/P/O/Q ? */ switch ( c = ptmcho(MSG10) ) /* get user's menu choice */ { case 1: continue; case 2: PANELS(pzero); /* clear out inp fields */ continue; case 3: dump_panel(PRNAME,TRUE); /* output to printer */ break; case 4: dump_panel(OFNAME,FALSE); /* output to disk */ break; case 5: PAFREE(&pantpcb); /* recover allocated space */ pantpcb.pf[0] = '\0'; /* force ask for panel name */ pantpcb.nf = 0; /* force read every field */ PAMLN = 0; /* reset message line */ goto newpanel; case 6: PAFREE(&pantpcb); /* recover allocated space */ quitting=TRUE; break; case 7: case 8: case 9: case 10: case 11: /* any numeric 1..9 */ case 12: case 13: case 14: case 15: PAPSLO = PAPSHI = c - 6; /* set level number */ PANELS(pdisp); PANELS(pshow); strcpy(tmp,MSG15); tmp[strlen(tmp)-1] = c + 42; pthalt(tmp); PANELS(pread); PANELS(funsh); PAPSLO = PAPSHI = 0; break; } } PAMLCL(); ptquit(); newpanel: ; } }