xref: /openbsd-src/usr.bin/mg/macro.c (revision 5b133f3f277e80f096764111e64f3a1284acb179)
1 /*	$OpenBSD: macro.c,v 1.18 2023/03/08 04:43:11 guenther Exp $	*/
2 
3 /* This file is in the public domain. */
4 
5 /*
6  *	Keyboard macros.
7  */
8 
9 #include <sys/queue.h>
10 #include <signal.h>
11 #include <stdio.h>
12 #include <stdlib.h>
13 
14 #include "def.h"
15 #include "key.h"
16 #include "macro.h"
17 
18 int inmacro = FALSE;	/* Macro playback in progress */
19 int macrodef = FALSE;	/* Macro recording in progress */
20 int macrocount = 0;
21 
22 struct line *maclhead = NULL;
23 struct line *maclcur;
24 
25 union macrodef macro[MAXMACRO];
26 
27 int
definemacro(int f,int n)28 definemacro(int f, int n)
29 {
30 	struct line	*lp1, *lp2;
31 
32 	macrocount = 0;
33 
34 	if (macrodef) {
35 		ewprintf("already defining macro");
36 		return (macrodef = FALSE);
37 	}
38 
39 	/* free lines allocated for string arguments */
40 	if (maclhead != NULL) {
41 		for (lp1 = maclhead->l_fp; lp1 != maclhead; lp1 = lp2) {
42 			lp2 = lp1->l_fp;
43 			free(lp1);
44 		}
45 		free(lp1);
46 	}
47 
48 	if ((maclhead = lp1 = lalloc(0)) == NULL)
49 		return (FALSE);
50 
51 	ewprintf("Defining Keyboard Macro...");
52 	maclcur = lp1->l_fp = lp1->l_bp = lp1;
53 	return (macrodef = TRUE);
54 }
55 
56 int
finishmacro(int f,int n)57 finishmacro(int f, int n)
58 {
59 	if (macrodef == TRUE) {
60 		macrodef = FALSE;
61 		ewprintf("End Keyboard Macro Definition");
62 		return (TRUE);
63 	}
64 	return (FALSE);
65 }
66 
67 int
executemacro(int f,int n)68 executemacro(int f, int n)
69 {
70 	int	 i, j, flag, num;
71 	PF	 funct;
72 
73 	if (macrodef ||
74 	    (macrocount >= MAXMACRO && macro[MAXMACRO - 1].m_funct
75 	    != finishmacro)) {
76 		dobeep();
77 		ewprintf("Macro too long. Aborting.");
78 		return (FALSE);
79 	}
80 
81 	if (macrocount == 0)
82 		return (TRUE);
83 
84 	inmacro = TRUE;
85 
86 	for (i = n; i > 0; i--) {
87 		maclcur = maclhead->l_fp;
88 		flag = 0;
89 		num = 1;
90 		for (j = 0; j < macrocount - 1; j++) {
91 			funct = macro[j].m_funct;
92 			if (funct == universal_argument) {
93 				flag = FFARG;
94 				num = macro[++j].m_count;
95 				continue;
96 			}
97 			if ((*funct)(flag, num) != TRUE) {
98 				inmacro = FALSE;
99 				return (FALSE);
100 			}
101 			lastflag = thisflag;
102 			thisflag = 0;
103 			flag = 0;
104 			num = 1;
105 		}
106 	}
107 	inmacro = FALSE;
108 	return (TRUE);
109 }
110